Compare commits

...

106 Commits

Author SHA1 Message Date
chapoi 8e0e2e1a8a UX: add fadeout to topic list on large vp 2025-06-10 11:16:08 +02:00
chapoi 14aa72ad99 UX: Mini fixes and tweaks (#179)
* Changing the category & tag dropdown back into their original form.
The breadcrumb idea isn't working well.

| BC | AC |
|--------|--------|
| ![CleanShot 2025-06-09 at 18 59
37@2x](https://github.com/user-attachments/assets/cbeb3aaf-ad0e-4085-8548-58ea0a521c95)
| ![CleanShot 2025-06-09 at 18 57
33@2x](https://github.com/user-attachments/assets/15db752b-4983-4b7f-b6f8-9a8ded9e6f9f)
|

* Alignment fix in chat navbar drawer

| BC | AC |
|--------|--------|
| ![CleanShot 2025-06-09 at 18 59
18@2x](https://github.com/user-attachments/assets/38c7dcee-dc77-4a44-ae8d-5ecb7910536b)
| ![CleanShot 2025-06-09 at 18 58
36@2x](https://github.com/user-attachments/assets/be699f88-4e5e-4d8c-ab4d-f6d1eca93037)
|
2025-06-09 19:41:18 +02:00
Jarek Radosz bf9fe07f67 DEV: Update linting config and run gjs-codemod (#177) 2025-06-06 12:15:57 +01:00
Jordan Vidrine 31249c4f27 UX: Remove unused line & fix ipad safari browser (#176) 2025-06-04 14:55:25 -05:00
Kris 581332c001 UX: fix mobile timeline in PWA (#174) 2025-06-04 14:55:02 -04:00
chapoi f5c4403423 UX: increase spacing of topic cards (#175)
Slightly bigger spacing to match the bigger avatars (bigger elements =>
more spacing to balance it out)
2025-06-04 16:04:11 +02:00
chapoi b72a3c1e95 UX: Topic cards v2 (#173)
This is the second iteration on the topic card design, in which we bring
back the OP and change the layout.

**Changes**:
* Show OP avatar
* Remove activity avatar and replace by reply icon
* Remove activity icon background
* Move category tag to top left
* Replace long activity copy ("…replied at…") with dot separator
* Change date formatting to `tiny`
* Adjust bulk select styling to new layout + align checkbox to top on
mobile VS keep centred on desktop

* Why: On desktop, the avatar is taking 2 lines (usually) and aligning
the checkbox vertically looks nice. Exception for excerpts, but since
that's only available for pinned topics atm that's a low occurrence. On
mobile, the topic card is 3 lines, with a smaller avatar, which makes
the checkbox "float" around a bit when centred. Hence aligning it to the
top, which for solid avatars aligns nicely too.

* CSS refactor: grid, breakpoints

Messages/bookmarks have not been changed.

| Description | Visual |
|--------|--------|
| Large topic list | ![CleanShot 2025-06-02 at 17 37
35@2x](https://github.com/user-attachments/assets/f232058e-dbf6-4689-abe3-65970464a3e3)|
| Large bulk edit | ![CleanShot 2025-06-02 at 17 37
17@2x](https://github.com/user-attachments/assets/03d86b5f-d62b-4449-9c0b-452ceb8be60c)
|
| Medium topic list | ![CleanShot 2025-06-02 at 17 39
01@2x](https://github.com/user-attachments/assets/80739641-cf8f-4095-938f-9781cac57a7d)
|
| Medium bulk edit | ![CleanShot 2025-06-02 at 17 39
24@2x](https://github.com/user-attachments/assets/6e9045af-734a-4f3f-830a-e03a2f06fdd8)
|
| Small topic list | ![CleanShot 2025-06-02 at 17 39
44@2x](https://github.com/user-attachments/assets/eeca80bc-6863-4026-8f19-b1b5cf6848f3)
|
| Small bulk edit | ![CleanShot 2025-06-02 at 17 40
00@2x](https://github.com/user-attachments/assets/cde7be08-cde2-4ff2-b81b-328d3d7be848)
|
| Messages page (remains unchanged) | ![CleanShot 2025-06-02 at 17 20
37@2x](https://github.com/user-attachments/assets/6512bfe9-a699-4c67-b709-166540ee6fde)
|
| Bookmark page (remains unchanged) | ![CleanShot 2025-06-02 at 17 21
01@2x](https://github.com/user-attachments/assets/f8f43638-e911-49cb-a0d5-ebcb51ccfba4)
|
2025-06-04 14:50:41 +02:00
Jordan Vidrine 0ed3912d63 UX: Fix topic card messages (#172) 2025-05-30 08:39:39 -05:00
Jordan Vidrine fc6d1b5b9d UX: RTL positioning of boxed view (#170) 2025-05-28 15:42:57 -05:00
Ella E. bd93d46ef4 DEV: Add screenshots (#169) 2025-05-23 21:33:01 -06:00
Kris 04d8684b59 UX: fix new topic badge in topic list (#167)
The theme implements this in a centralized way, so we need to remove the
core implementation.

before:


![image](https://github.com/user-attachments/assets/a9b37f79-d464-43e9-9298-3607180162ec)


after:


![image](https://github.com/user-attachments/assets/bd3c79b5-6371-4439-86a2-5f91e44f04ca)
2025-05-21 10:54:24 -04:00
Kris 79be7731b7 UX: adjust event date alignment with topic titles (#165)
this regressed slightly with core changes 

before:

![image](https://github.com/user-attachments/assets/550df0f8-fb8d-4af3-b4ec-5a61834d8a45)


after:

![image](https://github.com/user-attachments/assets/5c06f32d-ee31-444e-90f7-c31f9c44f642)
2025-05-21 09:59:21 -04:00
David Taylor fe1cb262dc UX: Allow clicking anywhere on the topic-list card (#166) 2025-05-21 13:37:21 +01:00
chapoi 25cc070a5b UX: fix low z-index for popup after changes to composer-drawer interaction (#164)
Fixing:
![CleanShot 2025-05-20 at 11 58
11@2x](https://github.com/user-attachments/assets/68611ead-71bf-42bf-bd87-183f589f4b82)

Consequence of #161
2025-05-20 14:22:21 +02:00
Kris 7982d60967 UX: add compatibility with the top contributors sidebar (#162)
Improves compatibility with
https://meta.discourse.org/t/top-contributors-sidebar/215110

Before:

![image](https://github.com/user-attachments/assets/08994458-0322-4725-a66b-0c91712e3a2a)


After: 

![image](https://github.com/user-attachments/assets/de231b57-d6da-42c0-852e-2bf915ee929e)

---------

Co-authored-by: Jarek Radosz <jarek@cvx.dev>
2025-05-19 11:26:11 -04:00
chapoi 90eae2d3f1 Chat drawer and peakmode (#161)
To avoid very strange positioning and sizing, I'm opting to keep the
chat in front of the composer, when in peak-mode.
Still not ideal, but better than before.

![CleanShot 2025-05-14 at 13 11
16@2x](https://github.com/user-attachments/assets/9b28f097-a63b-4bbb-a016-68cbcd04ee3c)
⬇️ 
![CleanShot 2025-05-14 at 13 10
57@2x](https://github.com/user-attachments/assets/10b9c17e-1207-4775-8933-0f6aca8c3ab6)

Due to the way peakmode positions itself, it's impossible to place the
chat flush next to it. And due to the way resizing works (frop the top
left, anchored right), it also can't be placed on any left-handed
alignment.
2025-05-16 12:24:05 +02:00
Joffrey JAFFEUX 948c60d656 FIX: do not error when no palettes are available (#160)
To repro this you had to unchecked all the "Color palette can be
selected by users" from the colors tab.
2025-05-12 19:18:15 -03:00
Kris 86d0c03b03 UX: handle opening composer from slide-in hamburger menu (#159) 2025-05-12 12:04:38 -04:00
Kris d749920db7 UX: improve mobile event badge positioning (#156) 2025-05-10 13:46:15 -04:00
Keegan George eda0db294d UX: Improve styles for add translation composer view (#158)
## 🔍 Overview
This update ensures styles in composer look appropriate for the new
composer add translation view (recently added here:
https://github.com/discourse/discourse/pull/32564)


## 📷 Screenshots

### ← Before
<img width="1473" alt="Screenshot 2025-05-08 at 11 58 54"
src="https://github.com/user-attachments/assets/76fec3f6-1cbf-4b57-a765-c2cf003ba177"
/>

### → After
<img width="1476" alt="Screenshot 2025-05-08 at 11 58 42"
src="https://github.com/user-attachments/assets/f17e8dc5-3230-4a1f-9072-28a3c7415958"
/>
2025-05-08 12:17:42 -07:00
Jarek Radosz c2b71c04a8 DEV: Update linting (#153) 2025-05-06 16:53:12 +01:00
Kris ec532d356e UX: exclude wizard from #main-outlet background styling (#155)
Only a tiny sliver of the background shows currently, which seems
accidental

Before:

![image](https://github.com/user-attachments/assets/815b9dec-7708-44a1-b360-7394e42cc4f6)


After:

![image](https://github.com/user-attachments/assets/b2eaf893-3e41-4321-b836-873b691589c5)
2025-05-05 12:35:14 -04:00
Kris 755a666dae UX: hide bootstrap mode from header (#154)
There are multiple header elements that get in the way, and we can't
really manage the position of this button well without a better
full-width solution... so I think it makes sense to hide it for now


Before:

![image](https://github.com/user-attachments/assets/07009232-d188-4a5f-9381-0e1d4479512b)

After: 

![image](https://github.com/user-attachments/assets/91a0f01a-3d12-4f89-9d7f-0050abdd47e9)
2025-05-05 12:35:00 -04:00
Keegan George 4b159e9296 UX: New topic button shouldn't appear in AI conversations page (#152)
## 🔍 Overview
This update ensures that the sidebar new topic button isn't shown on the
AI conversations sidebar. It also styles the new conversation button to
make use of Horizon's accent color

## 📸 Screenshots

### ← Before
<img width="1228" alt="Screenshot 2025-05-02 at 14 16 41"
src="https://github.com/user-attachments/assets/b187d31e-881a-4c34-b663-f4b55b8bc565"
/>

### → After
<img width="1232" alt="Screenshot 2025-05-02 at 14 15 34"
src="https://github.com/user-attachments/assets/987cfba3-ad7c-49a9-80d8-14c3e52dd5c0"
/>
2025-05-05 09:27:28 -07:00
Kris e53184ac28 UX: fix experimental new new positioning (#151)
These styles were added for bulk select positioning, but turns out they
weren't needed anyway

before:

![image](https://github.com/user-attachments/assets/bf752846-cb51-4872-9cb7-2d98ab7f5c8f)

after:

![image](https://github.com/user-attachments/assets/4a25c776-b88c-4be6-b186-31973c6b5e05)
2025-04-25 11:35:00 -04:00
Kris a6293aa24b UX: text logo line-height fix (#150)
Minor adjustment to avoid clipping descenders 


before:

![image](https://github.com/user-attachments/assets/bc68416b-ab04-4a62-8bff-ec8164284380)


after: 

![image](https://github.com/user-attachments/assets/30296e9c-4e8d-446f-8ee4-f0583e6c3e68)
2025-04-24 14:22:07 -04:00
Kris 45cc99a2e0 UX: better full-width support for wide logos (#149)
Helps avoid situations like this:


![image](https://github.com/user-attachments/assets/78adec74-8fb7-457f-b592-da1b56a98b1a)


Some examples...


text-logos

![image](https://github.com/user-attachments/assets/c87333cb-727a-4167-af76-a5db0b3cd20c)

![image](https://github.com/user-attachments/assets/8cc62ab9-4f3e-4697-a763-851dc21aa2ec)

![image](https://github.com/user-attachments/assets/e36ffa7e-a3a9-463a-b448-833da2b3bc69)

image-logos

![image](https://github.com/user-attachments/assets/962f33c1-d83c-4d74-a707-ec1fb867d557)

![image](https://github.com/user-attachments/assets/0014505a-bfab-4616-962a-c1a5fa30938e)

![image](https://github.com/user-attachments/assets/32d9730a-1a43-49ac-b160-b6dd610f4482)
2025-04-24 14:04:06 -04:00
Jordan Vidrine 806b800f1f UX: adjust styles to meet core changes (#148) 2025-04-23 14:44:00 -05:00
Jordan Vidrine 70af5fc68a UX: Adjust spacing for more room (#146) 2025-04-21 16:36:03 -05:00
Kris b1a9389a04 UX: minor breakpoint gap fix (#147)
Reported here:
https://meta.discourse.org/t/help-us-test-horizon-our-newest-theme/360484/55?u=awesomerobot

We have a 1px gap here where we get kind of a half-container 

Before:

![image](https://github.com/user-attachments/assets/0d355156-c579-418d-a1d1-9d624c61bc12)



After:

![image](https://github.com/user-attachments/assets/ce96bf6b-c8a8-4fd2-b5b0-56d37382284d)
2025-04-18 14:08:34 -04:00
Martin Brennan f9603a24ea DEV: Rename search -> welcome banner (#144)
Horizon is targeting the welcome banner not the search component
anymore, update CSS class names and rename the file to make this clearer
2025-04-18 12:23:44 +10:00
Jordan Vidrine bf2fb463ae UX: Modernize spacing a bit (#145) 2025-04-17 21:16:43 -05:00
Martin Brennan 07113ca324 DEV: Slight refactor and add specs for composer peek (#142)
Followup cf9fd864dd
2025-04-18 09:12:43 +10:00
Kris d67ec3ac5f FIX: remove SCSS mixed declarations (#143)
This fixes the SCSS mixed declaration errors (most noticeable while
running rspec)
2025-04-17 17:27:13 -04:00
Kris cf9fd864dd DEV: implement composer peek mode directly in theme (#141)
This implements the [composer
peek](https://github.com/discourse/composer-peek) component directly
into the theme, and makes some minor adjustments to match theme styles:


![image](https://github.com/user-attachments/assets/e4272a11-6570-4392-945f-c509cf4debd6)
2025-04-16 17:10:23 -04:00
Kris 36899bbbaa UX: make theme compatible with AI gists (#140)
Before (only pinned topic excerpts, no gist toggle):

![image](https://github.com/user-attachments/assets/7a1b78b8-e115-4c96-9ebf-52d2c1237eea)


After (gists can be toggled on): 

![image](https://github.com/user-attachments/assets/9e6786be-3817-4420-8142-1c5f7cad54ea)


This puts the gists in the same place as the theme places excerpts and
uses the same styles. It also follows the theme pattern of hiding
excerpts/gists on mobile.
2025-04-16 15:34:52 -04:00
Jordan Vidrine 651cf2794c UX: remove square avatar from topic posts (#139) 2025-04-16 12:04:41 -05:00
Jordan Vidrine e9e166ca3a FIX: Search header index (#138) 2025-04-15 20:46:27 -05:00
Kris 81141cc66f UX: update about.json, readme (#137)
Just a little bit of metadata cleanup
2025-04-15 09:19:14 -04:00
Martin Brennan b23c4764a2 DEV: Put full width styles into their own file (#132)
Followup f1d5b69293

We want to make it super clear that this is to be removed when we merge
full width into core, keeping it in desktop.scss together with other
styles will make that harder.
2025-04-15 13:46:20 +10:00
Jordan Vidrine 7ab29303dd UX: Mobile composer fixes (#136) 2025-04-14 16:33:30 -05:00
Kris 776071fdb0 UX: adjust disabled create button tooltip styles (#135) 2025-04-14 16:22:17 -05:00
Jordan Vidrine 2d193b4d7a UX: Quick fixes (#134) 2025-04-14 15:52:12 -05:00
Jordan Vidrine 24165a53a6 UX: Login layout fixes (#133) 2025-04-14 13:59:24 -05:00
Kris 3a9917862d UX: main-outlet needs dynamic bottom padding when composer open (#119)
When the composer is open the `#main-outlet`'s bottom padding needs to
match the composer height, so the content behind the composer can be
scrolled into view.

Reported here:
https://meta.discourse.org/t/help-us-test-horizon-our-newest-theme/360484/26?u=awesomerobot
2025-04-14 09:06:42 -04:00
Kris 0cd52c07fe UX: fix topic progress height (#118)
Before: 

![image](https://github.com/user-attachments/assets/b41d9c5f-6a7a-4cae-aa87-375e54b94bf9)


After:

![image](https://github.com/user-attachments/assets/e6969dcd-83b3-4e3c-a868-1dbd70ecf195)
2025-04-14 08:59:33 -04:00
Kris 1e6a4a8a57 DEV: port sidebar new topic component into theme (#129)
This moves the [sidebar new topic button
component](https://github.com/discourse/discourse-sidebar-new-topic-button)
into the theme directly

If you have installed this theme previously, you should manually remove
the component.
2025-04-14 08:58:46 -04:00
Jordan Vidrine b40a5a6e9a UX: Adjust avatar spacing (#131) 2025-04-12 09:03:55 -05:00
Jordan Vidrine 3a0a5b0f30 UX: Fix chat backgrounds (#130) 2025-04-11 17:06:41 -05:00
Jordan Vidrine e3aed16e2b UX: remove gap on avatars in PM list (#128) 2025-04-11 15:47:12 -05:00
Jordan Vidrine 23f4362f7e UX: Visual fixes (#127) 2025-04-11 15:33:58 -05:00
Kris f1d5b69293 DEV: port full-width component to be included directly (#126)
Removes the [full-width
component](https://github.com/discourse/discourse-full-width-component)
dependency by adding most of the code directly to the theme. There was
one grid definition in the CSS I ended up removing because it was
conflicting with an existing override in the theme.

Anyone who has previously installed the theme should manually remove the
full-width component from it.
2025-04-11 15:46:25 -04:00
Jordan Vidrine 18ffe04242 UX: New PM design (#125) 2025-04-11 13:43:17 -05:00
David Taylor b220d87a0d DEV: Trigger basic-html view for unsupported browsers (#124) 2025-04-10 20:39:30 +01:00
Kris 8e5cef819d UX: fix account activation layout (#123)
fixes this too-wide layout issue


![image](https://github.com/user-attachments/assets/9b2c8a1a-e395-44b5-acdb-cb289f69dcfb)
2025-04-10 13:19:52 -04:00
chapoi 2653732bc3 UX: post notice styling (#122)
![CleanShot 2025-04-10 at 11 14
07@2x](https://github.com/user-attachments/assets/c5c8f918-fbf4-4a39-b65d-09ddf045fe74)
⬇️ 
![CleanShot 2025-04-10 at 11 13
28@2x](https://github.com/user-attachments/assets/449d824a-15e3-49fb-9acb-25cee76e8acb)
2025-04-10 13:56:17 +02:00
Jordan Vidrine 2a0f5ec599 UX: font set experimental screen styles (#121) 2025-04-09 12:12:10 -05:00
Loïc Guitaut 3c7ccc97a7 DEV: Add system spec to check core features are working fine (#117) 2025-04-09 15:41:21 +02:00
Kris 2674364309 DEV: use wildcard selector for common container behavior (#120) 2025-04-08 16:01:08 -05:00
chapoi 5299986ed1 UX: iteration for the timeline scroll design (#116)
Attempt to make the timeline less eye-drawing, while still enhancing the
feel of "this is a draggable area" by emphasising the handle. Also added
a slight decrease of width.

| Before | After |
|--------|--------|
| ![CleanShot 2025-04-07 at 20 17
29@2x](https://github.com/user-attachments/assets/7997a797-1ffa-43b7-94fa-010974aeae51)
| ![CleanShot 2025-04-07 at 20 17
02@2x](https://github.com/user-attachments/assets/7372e1e2-8530-4045-bcdf-0ef73aa6698e)
|
2025-04-08 18:31:10 +02:00
Jordan Vidrine 34b26abb6e UX: fix width (#114) 2025-04-04 14:04:58 -05:00
Jordan Vidrine c735718f1b DEV: Add more user logic (#113) 2025-04-04 11:47:00 -05:00
Jordan Vidrine cdcbffc483 UX: More color fixes (#111) 2025-04-03 16:13:23 -05:00
Jordan Vidrine d8c44934f4 UX: Theme name change (#112) 2025-04-03 16:13:02 -05:00
Martin Brennan 00b2402cbb DEV: Core feature spec refinement (#106)
Followup e4b99976eb

This allows us to skip core feature specs more granularly,
since the topic ones work fine except create for example.

Also adds a topic create spec, since this theme uses the sidebar
new topic button component. We can rely on the /new-topic route
instead.
2025-04-03 13:40:27 +10:00
Kris c9c468c677 UX: fix PM user input spacing (#110)
Before:


![image](https://github.com/user-attachments/assets/3327adce-b26e-4644-82fe-d4f9611ad8e0)

After:


![image](https://github.com/user-attachments/assets/33f6a819-fa34-40f1-98de-469ab0f161f0)
2025-04-02 15:07:51 -04:00
Kris 85d94e9eca UX: fix cakeday & user directory containers (#109)
Before:


![image](https://github.com/user-attachments/assets/dbc14156-2def-42c1-bbc4-b2366a9b89fa)


![image](https://github.com/user-attachments/assets/92554725-ce2d-4756-9f9e-e49b91f0c227)


After:


![image](https://github.com/user-attachments/assets/a2c90617-6efa-4bdb-8149-cd7d5cea6e95)


![image](https://github.com/user-attachments/assets/2188f0be-58ef-4996-8628-57705cc6d52c)
2025-04-02 15:07:35 -04:00
Jordan Vidrine d0078cdd3e UX: Adjust icon colors (#108) 2025-04-02 10:50:37 -05:00
Jordan Vidrine 759fd0b218 UX: Header outline (#107) 2025-04-02 08:28:08 -05:00
Jordan Vidrine 1c85ae4626 UX: More accessible colors (#105) 2025-04-01 20:01:29 -05:00
Jordan Vidrine f4c6876923 UX: Topic excerpt fix (#104) 2025-04-01 15:09:04 -05:00
Martin Brennan e4b99976eb DEV: Add core feature spec (#100) 2025-04-01 12:49:37 -05:00
chapoi def09bcca5 UX: adapt topic card layout for bookmarks & assigned list (#97) 2025-04-01 12:48:52 -05:00
Jordan Vidrine 05d4b79fc9 UX: Add hover colors (#103) 2025-04-01 12:25:52 -05:00
Kris 5570fb9feb UX: fix group page container, round border (#102)
Fixes the spacing on the group container and rounds the header 

Before:


![image](https://github.com/user-attachments/assets/3384841a-82b0-4f17-a0be-a32bd405bd29)


After:


![image](https://github.com/user-attachments/assets/1450cb2d-bd7a-4fb4-b7a8-b800b8b40d0d)
2025-04-01 12:50:19 -04:00
Jordan Vidrine 5bbba7cacc UX: Define header colors (#101) 2025-04-01 09:52:12 -05:00
Martin Brennan 96da1d3439 FIX: Issues with FOUC and dark mode when switching palettes (#99)
Followup 6a4b979514

In this commit I changed how we load the selected palette
stylesheet so the system specs would know when the CSS is actually
loaded, however this introduced an issue where the user would see
a FOUC when switching palettes. I also introduced a bug where
if you chose to force dark mode then switched the palette, you would
see light mode instead.

This commit fixes both issues, by swapping the CSS link with a preloaded
one then waiting for the preload before switching the href of the
existing link, and removes `mode` shenanigans causing the light mode
issue.
2025-04-01 13:07:26 +10:00
Kris 878da19552 UX: fix category nav padding on small screens (#98)
This adjusts the active state of the dropdown by employing negative
margin to compensate for the padding

before:

![image](https://github.com/user-attachments/assets/e8c8a544-3527-4d6c-a513-0291a6a15ab5)


after:

![image](https://github.com/user-attachments/assets/4a53a0ee-a07d-43b0-9ab6-3542d86bbe8c)
2025-03-31 17:02:30 -04:00
chapoi 17bd1c2346 UX: fix chat border (#96) 2025-03-31 10:50:44 +02:00
Martin Brennan 6a4b979514 FIX: Color palette switching when Horizon is not default (#95)
When Horizon is not the default theme, and the color palette
switcher is used, we were ending up in a broken CSS state because
the color definitions were not loaded correctly when calling
`/color-scheme-stylesheet/` to get the new stylesheet URLs.

The problem was that we were not giving the theme ID to this URL,
we were only doing `/color-scheme-stylesheet/:palette_id`, not
`/color-scheme-stylesheet/:palette_id/:theme_id`, so the theme
color definitions like the ones that define the background color
were not loaded.

This commit fixes the issue and also changes to recreating the
`<link>` tags for the CSS in the head so we can check if they
are loaded correctly for easier testing in system specs.
2025-03-31 18:23:07 +10:00
Jordan Vidrine b4e451e64b DEV: Experimenting with using built in core color palettes for the color picking component (#71)
This PR is the beginning of converting the color picker to use built in
core color palettes.
The `color_schemes` defined in `about.json` are created in core when the
theme is imported,
and we then show all user-selectable color palettes in this sidebar
footer menu.

An important caveat here is that all of the Horizon themes must be
changed to `user_selectable`
otherwise they will not show up in the color palette selector in the
sidebar.

When choosing a color palette that also has a corresponding dark color
palette,
*both* light mode and dark mode are correctly saved with the color
palette(s) chosen,
using the color palette cookie we already have in core.

Anon users can also set a palette, which will be saved in a cookie.

---------

Co-authored-by: Sérgio Saquetim <saquetim@discourse.org>
Co-authored-by: Martin Brennan <martin@discourse.org>
Co-authored-by: Osama Sayegh <asooomaasoooma90@gmail.com>
2025-03-31 13:28:28 +10:00
chapoi 0473f90cd9 Lower z-index of powered-by-discourse badge (#93) 2025-03-30 20:33:59 -05:00
Jordan Vidrine 3e3f410839 UX: More card fixes (#94) 2025-03-28 16:43:52 -05:00
Jordan Vidrine 2046f525d4 UX: More logic for title columns (#87) 2025-03-28 10:49:28 -05:00
chapoi 9945f1d899 FIX: remove overflow prop (#91) 2025-03-28 08:27:36 -05:00
chapoi f70524a44b UX: fix minimised draft bg colour for composer (#89)
Followup fix for #84
2025-03-28 14:17:45 +01:00
Martin Brennan 0a416d317e FIX: Messed up CSS grid on messages list (#88)
This needs a better follow-up, but the messages topic list
is currently busted. Removing the overridden topic-list-item
grid for messages helps.
2025-03-28 12:39:49 +10:00
chapoi 910bc855c1 Composer styling on desktop (#84) 2025-03-27 16:41:20 -05:00
chapoi e20b83b79d Misc mobile fixes (#83) 2025-03-27 16:35:08 -05:00
Jordan Vidrine e7de006a23 UX: Topic list layout changes (#85) 2025-03-27 16:31:46 -05:00
Jordan Vidrine eff8628223 DEV: Fix spec (#86) 2025-03-27 16:31:28 -05:00
Jordan Vidrine a84682c0d0 FIX: Bulk select fix (#81)
This PR fixes bulk select on the new topic cards.
2025-03-27 10:03:40 +10:00
Jordan Vidrine adb1e4dcf2 UX: Change title fonts, etc (#80) 2025-03-26 14:08:42 -05:00
Jordan Vidrine d300cf9d0f UX: New topic card layout (#79) 2025-03-26 10:47:52 -05:00
Kris 6766b94232 UX: add tags-index container (#78) 2025-03-25 16:18:17 -04:00
Jordan Vidrine af82802548 UX: Topic list card fixes for assignments & bookmarks (#76) 2025-03-25 15:11:49 -05:00
Kris 943dd4e2d2 UX: change category nav background on mobile (#77) 2025-03-25 15:54:03 -04:00
Jordan Vidrine 1a372b7edc fix z index for input menu (#75) 2025-03-25 10:08:16 -05:00
Kris f786eae910 UX: set border radius on PMs (#74) 2025-03-24 15:22:25 -04:00
Jordan Vidrine dabd9a159a DEV: Use new is_hot_topic serializer (#73) 2025-03-24 12:05:10 -05:00
Jordan Vidrine 969e2b7969 begin migration of colors (#72) 2025-03-21 09:44:09 -05:00
chapoi ade14d7f54 Welcome banner: slight zindex increase (#70) 2025-03-21 11:55:29 +01:00
chapoi 30cb6bbf59 UX: Z-index welcome banner (#68)
* UX: increase z-index of welcome banner

* UX: lower z-index of sticky list-controls
2025-03-20 19:13:52 +01:00
Jordan Vidrine bee6e4e3c5 init (#69) 2025-03-20 09:43:40 -05:00
Kris 7f6b0df5bf UX: move and restyle bulk select on desktop (#65) 2025-03-20 08:42:11 -04:00
Martin Brennan 274e5f7a1f UX: Add theme settings and value transformers (#67)
This commit adds the above for these core site
settings:

* search_experience
* enable_welcome_banner

Since for horizon we want better control of
the default experience of these settings OOTB.

See also https://github.com/discourse/discourse/pull/31917
2025-03-20 15:38:46 +10:00
68 changed files with 4073 additions and 2802 deletions
+2
View File
@@ -0,0 +1,2 @@
< 3.5.0.beta5-dev: 31249c4f27d93e83c6b83d42d93974522a9a612e
+60 -44
View File
@@ -1,8 +1,9 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (7.2.1.1)
activesupport (8.0.2)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
@@ -12,68 +13,83 @@ GEM
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
ast (2.4.2)
base64 (0.2.0)
bigdecimal (3.1.8)
concurrent-ruby (1.3.4)
connection_pool (2.4.1)
drb (2.2.1)
i18n (1.14.6)
uri (>= 0.13.1)
ast (2.4.3)
base64 (0.3.0)
benchmark (0.4.1)
bigdecimal (3.2.2)
concurrent-ruby (1.3.5)
connection_pool (2.5.3)
drb (2.2.3)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
json (2.7.2)
language_server-protocol (3.17.0.3)
logger (1.6.1)
minitest (5.25.1)
parallel (1.26.3)
parser (3.3.5.0)
json (2.12.2)
language_server-protocol (3.17.0.5)
lint_roller (1.1.0)
logger (1.7.0)
minitest (5.25.5)
parallel (1.27.0)
parser (3.3.8.0)
ast (~> 2.4.1)
racc
prettier_print (1.2.1)
prism (1.4.0)
racc (1.8.1)
rack (3.1.10)
rack (3.1.15)
rainbow (3.1.1)
regexp_parser (2.9.2)
rubocop (1.67.0)
regexp_parser (2.10.0)
rubocop (1.76.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.4, < 3.0)
rubocop-ast (>= 1.32.2, < 2.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.45.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.32.3)
parser (>= 3.3.1.0)
rubocop-capybara (2.21.0)
rubocop (~> 1.41)
rubocop-discourse (3.8.2)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.45.0)
parser (>= 3.3.7.2)
prism (~> 1.4)
rubocop-capybara (2.22.1)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-discourse (3.12.1)
activesupport (>= 6.1)
rubocop (>= 1.59.0)
rubocop-capybara (>= 2.0.0)
rubocop-factory_bot (>= 2.0.0)
rubocop-rails (>= 2.25.0)
lint_roller (>= 1.1.0)
rubocop (>= 1.73.2)
rubocop-capybara (>= 2.22.0)
rubocop-factory_bot (>= 2.27.0)
rubocop-rails (>= 2.30.3)
rubocop-rspec (>= 3.0.1)
rubocop-rspec_rails (>= 2.30.0)
rubocop-factory_bot (2.26.1)
rubocop (~> 1.61)
rubocop-rails (2.26.2)
rubocop-rspec_rails (>= 2.31.0)
rubocop-factory_bot (2.27.1)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rails (2.32.0)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
rubocop (>= 1.52.0, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rspec (3.1.0)
rubocop (~> 1.61)
rubocop-rspec_rails (2.30.0)
rubocop (~> 1.61)
rubocop-rspec (~> 3, >= 3.0.1)
rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.44.0, < 2.0)
rubocop-rspec (3.6.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec_rails (2.31.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec (~> 3.5)
ruby-progressbar (1.13.0)
securerandom (0.3.1)
securerandom (0.4.1)
syntax_tree (6.2.0)
prettier_print (>= 1.2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.6.0)
unicode-display_width (3.1.4)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
uri (1.0.3)
PLATFORMS
ruby
@@ -83,4 +99,4 @@ DEPENDENCIES
syntax_tree
BUNDLED WITH
2.5.21
2.6.9
+2 -4
View File
@@ -1,5 +1,3 @@
# next-gen
Horizon is a simple, beautiful theme that improves the out-of-the-box experience for Discourse sites.
**Theme Summary**
For more information, please see: **url to meta topic**
https://meta.discourse.org/t/horizon-theme/360486
+121 -26
View File
@@ -1,40 +1,135 @@
{
"name": "Horizon Theme",
"name": "Horizon",
"authors": "Design Team",
"about_url": "TODO: Put your theme's public repo or Meta topic URL here",
"license_url": "TODO: Put your theme's LICENSE URL here",
"learn_more": "TODO",
"about_url": "https://meta.discourse.org/t/horizon-theme/360486",
"license_url": "https://github.com/discourse/horizon/blob/main/LICENSE",
"learn_more": "https://meta.discourse.org/t/installing-a-theme-or-theme-component/63682",
"theme_version": "0.0.1",
"minimum_discourse_version": null,
"maximum_discourse_version": null,
"assets": {},
"modifiers": {
"svg_icons": ["fire"]
"svg_icons": ["fire"],
"serialize_topic_is_hot": true
},
"components": [
"https://github.com/discourse/discourse-sidebar-new-topic-button.git",
"https://github.com/discourse/discourse-full-width-component.git"
],
"color_schemes": {
"Horizon": {
"primary": "1A1A1A",
"secondary": "ffffff",
"header_background": "f5f8ff",
"tertiary": "595bca",
"tertiary-low": "d8d9f3",
"tertiary-50": "f5f8ff",
"selected": "d8d9f3",
"hover": "ebebf9"
"tertiary-med-or-tertiary": "595bca",
"selected": "d7dfff",
"header_background": "ffffff",
"header_primary": "1A1A1A",
"hover": "E1E8FF"
},
"Horizon Dark": {
"primary": "F1EFF9",
"secondary": "1e1a36",
"header_background": "00091d",
"header_primary": "F5F8FF",
"tertiary": "6465ab",
"tertiary-50": "131124",
"selected": "1e1a36",
"hover": "131124"
"primary": "ffffff",
"secondary": "1A1A1A",
"tertiary": "595bca",
"tertiary-med-or-tertiary": "595bca",
"selected": "3b3e56",
"header_background": "1A1A1A",
"header_primary": "ffffff",
"hover": "333548"
},
"Royal": {
"primary": "1A1A1A",
"secondary": "ffffff",
"tertiary": "1F7BC1",
"tertiary-med-or-tertiary": "1F7BC1",
"selected": "c7e3ff",
"header_background": "ffffff",
"header_primary": "1A1A1A",
"hover": "D6EBFF"
},
"Royal Dark": {
"primary": "ffffff",
"secondary": "1A1A1A",
"tertiary": "1F7BC1",
"tertiary-med-or-tertiary": "1F7BC1",
"selected": "3a455f",
"header_background": "1A1A1A",
"header_primary": "ffffff",
"hover": "323B4E"
},
"Clover": {
"primary": "1A1A1A",
"secondary": "ffffff",
"tertiary": "39845B",
"tertiary-med-or-tertiary": "39845B",
"selected": "c6f1d5",
"header_background": "ffffff",
"header_primary": "1A1A1A",
"hover": "D5F5E0"
},
"Clover Dark": {
"primary": "ffffff",
"secondary": "1A1A1A",
"tertiary": "39845B",
"tertiary-med-or-tertiary": "39845B",
"selected": "47594e",
"header_background": "1A1A1A",
"header_primary": "ffffff",
"hover": "3C4A40"
},
"Lily": {
"primary": "1A1A1A",
"secondary": "ffffff",
"tertiary": "cc338c",
"tertiary-med-or-tertiary": "cc338c",
"selected": "ffc8ee",
"header_background": "ffffff",
"header_primary": "1A1A1A",
"hover": "FFD7F3"
},
"Lily Dark": {
"primary": "ffffff",
"secondary": "1A1A1A",
"tertiary": "cc338c",
"tertiary-med-or-tertiary": "cc338c",
"selected": "5f3e4e",
"header_background": "1A1A1A",
"header_primary": "ffffff",
"hover": "4E3640"
},
"Violet": {
"primary": "1A1A1A",
"secondary": "ffffff",
"tertiary": "9b15de",
"tertiary-med-or-tertiary": "9b15de",
"selected": "feccff",
"header_background": "ffffff",
"header_primary": "1A1A1A",
"hover": "FFD9FF"
},
"Violet Dark": {
"primary": "ffffff",
"secondary": "1A1A1A",
"tertiary": "9b15de",
"tertiary-med-or-tertiary": "9b15de",
"selected": "4c385c",
"header_background": "1A1A1A",
"header_primary": "ffffff",
"hover": "40314C"
},
"Marigold": {
"primary": "1A1A1A",
"secondary": "ffffff",
"tertiary": "d3881f",
"tertiary-med-or-tertiary": "d3881f",
"selected": "ffdcb2",
"header_background": "ffffff",
"header_primary": "1A1A1A",
"hover": "FFE6C6"
},
"Marigold Dark": {
"primary": "ffffff",
"secondary": "1A1A1A",
"tertiary": "d3881f",
"tertiary-med-or-tertiary": "d3881f",
"selected": "6c5b49",
"header_background": "1A1A1A",
"header_primary": "ffffff",
"hover": "584B3E"
}
}
},
"screenshots": ["screenshots/light.png", "screenshots/dark.png"]
}
+105
View File
@@ -0,0 +1,105 @@
html {
--accent-color: #{$tertiary} !important;
--accent-text-color: #fff;
// Background Colors
--background-color: light-dark(
oklch(from #{$tertiary} 96% calc(c * 0.125) h),
oklch(from #{$tertiary} 10% 0.025 h)
) !important;
--d-content-background: light-dark(
oklch(from #{$secondary} calc(2 * l) c h),
oklch(from #{$secondary} l c h)
) !important;
// HeaderColors
--header_primary-low-mid: light-dark(
oklch(from #{$tertiary} 73.5% calc(c * 0.5) h),
oklch(from #{$tertiary} l calc(c * 0.25) h)
) !important;
--header_primary-medium: light-dark(
oklch(from #{$tertiary} 54% calc(c * 0.5) h),
oklch(from #{$tertiary} calc(l * 1.35) calc(c * 0.25) h)
) !important;
// Sidebar Colors
--d-sidebar-border-color: light-dark(
oklch(from #{$tertiary} 88% calc(c * 0.25) h),
oklch(from #{$tertiary} calc(l * 0.7) calc(c * 0.25) h)
) !important;
--d-sidebar-link-color: light-dark(
oklch(from #{$tertiary} calc(l * 0.8) calc(c * 0.25) h),
oklch(from #{$tertiary} calc(l * 1.5) calc(c * 0.25) h)
) !important;
--d-sidebar-active-color: #{$primary} !important;
--d-sidebar-suffix-color: light-dark(
oklch(from #{$tertiary} l calc(c * 0.9) h),
oklch(from #{$tertiary} l calc(c * 0.9) h)
) !important;
// Other Colors
--d-selected: light-dark(
oklch(from #{$tertiary} 92% calc(c * 0.5) h),
oklch(from #{$tertiary} calc(l * 0.7) calc(c * 0.25) h)
) !important;
--d-nav-color--active: light-dark(
oklch(from #{$tertiary} l c h),
oklch(from #{$tertiary} calc(l * 1.2) c h)
) !important;
--d-nav-color--hover: light-dark(
oklch(from #{$tertiary} l c h),
oklch(from #{$tertiary} calc(l * 1.2) c h)
) !important;
--link-color: light-dark(
oklch(from #{$tertiary} l c h),
oklch(from #{$tertiary} calc(l * 0.95) c h)
) !important;
--link-color-hover: light-dark(
oklch(from #{$tertiary} l c h),
oklch(from #{$tertiary} calc(l * 1.5) calc(c * 2.25) h)
) !important;
--tertiary-hover: #{$tertiary} !important;
// Search Colors
--search-color: light-dark(
oklch(from #{$tertiary} l c h),
oklch(from #{$tertiary} calc(l * 1.5) calc(c * 0.25) h)
) !important;
// Topic Card Colors
--topic-card-shadow: light-dark(
oklch(from #{$tertiary} calc(l * 1.85) calc(c * 0.5) h),
oklch(from #{$tertiary} calc(l * 0.2) calc(c * 0.01) h / 0.25)
) !important;
// Button Colors
--button-box-shadow: light-dark(
oklch(from #{$tertiary} calc(l * 1.5) calc(c * 0.35) h),
oklch(from #{$tertiary} calc(l * 0.75) calc(c * 0.5) h)
) !important;
--d-sidebar-highlight-hover-icon: var(--d-sidebar-link-color) !important;
--d-sidebar-highlight-hover-background: var(--d-selected) !important;
--d-sidebar-link-icon-color: var(--d-sidebar-link-color) !important;
--d-sidebar-header-color: var(--d-sidebar-link-color) !important;
--d-sidebar-header-icon-color: var(--d-sidebar-link-color) !important;
--d-sidebar-active-suffix-color: var(--d-sidebar-suffix-color) !important;
--d-sidebar-background: var(--background-color) !important;
--d-sidebar-footer-fade: var(--background-color) !important;
--d-sidebar-prefix-background: var(--d-selected) !important;
--d-sidebar-active-prefix-background: light-dark(
oklch(from var(--d-selected) calc(l * 0.85) c h),
oklch(from var(--d-selected) calc(l * 0.7) c h)
) !important;
--d-sidebar-highlight-prefix-background: light-dark(
oklch(from var(--d-selected) calc(l * 0.85) c h),
oklch(from var(--d-selected) calc(l * 0.7) c h)
) !important;
--d-sidebar-highlight-suffix-color: var(
--d-sidebar-active-suffix-color
) !important;
--d-sidebar-highlight-color: var(--primary) !important;
--d-sidebar-highlight-background: var(--d-selected) !important;
--d-sidebar-section-link-icon-size: 1em !important;
--d-hover: oklch(from var(--d-selected) l c h / 0.75) !important;
--d-input-bg-color: var(--d-content-background) !important;
}
+4 -2
View File
@@ -2,16 +2,18 @@
@import "buttons";
@import "chat";
@import "color-choice";
@import "color-exploration";
@import "composer";
@import "composer-peek-mode";
@import "header";
@import "hiddenstuff";
@import "login";
@import "main";
@import "misc";
@import "mobile-stuff";
@import "nav-pills";
@import "search-banner";
@import "welcome-banner";
@import "sidebar";
@import "sidebar-new-topic-button";
@import "topic";
@import "topic-cards";
@import "variables";
+7
View File
@@ -0,0 +1,7 @@
<script>
if (!CSS.supports("(color: hsl(from white h s l))")) {
window.unsupportedBrowser = true;
window.I18n.translations[I18n.locale].js.browser_update =
'The Horizon theme does not support your browser. Please update your browser, or <a href="?safe_mode=no_themes">switch to safe mode</a>.';
}
</script>
+2
View File
@@ -0,0 +1,2 @@
@import "desktop-horizon-fixes";
@import "desktop-full-width";
@@ -0,0 +1,6 @@
import { apiInitializer } from "discourse/lib/api";
import ComposerPeekModeToggle from "../components/composer-peek-mode-toggle";
export default apiInitializer("1.8.0", (api) => {
api.renderInOutlet("before-composer-toggles", ComposerPeekModeToggle);
});
@@ -0,0 +1,16 @@
import { apiInitializer } from "discourse/lib/api";
export default apiInitializer("0.8", (api) => {
document.body.classList.add("full-width-enabled");
// When the sidebar is visible, force the HomeLogo to be in an 'un-minimized' state.
api.registerValueTransformer?.(
"home-logo-minimized",
({ value, context }) => {
if (value && context.showSidebar) {
return false;
}
return value;
}
);
});
@@ -0,0 +1,10 @@
import { apiInitializer } from "discourse/lib/api";
export default apiInitializer("0.8", (api) => {
api.registerValueTransformer(
"hamburger-dropdown-click-outside-exceptions",
({ value }) => {
return [...value, ".topic-drafts-menu-content"];
}
);
});
@@ -0,0 +1,16 @@
import { apiInitializer } from "discourse/lib/api";
import ExperimentalScreen from "../components/experimental-screen";
import UserColorPaletteSelector from "../components/user-color-palette-selector";
export default apiInitializer("1.8.0", (api) => {
api.renderInOutlet("above-main-container", ExperimentalScreen);
api.renderInOutlet("sidebar-footer-actions", UserColorPaletteSelector);
api.registerValueTransformer("site-setting-enable-welcome-banner", () => {
return settings.enable_welcome_banner;
});
api.registerValueTransformer("site-setting-search-experience", () => {
return settings.search_experience;
});
});
@@ -1,8 +0,0 @@
import { apiInitializer } from "discourse/lib/api";
import CustomColorHtmlClass from "../components/custom-color-html-class";
import ExperimentalScreen from "../components/experimental-screen";
export default apiInitializer("1.8.0", (api) => {
api.renderInOutlet("above-main-container", ExperimentalScreen);
api.renderInOutlet("above-main-container", CustomColorHtmlClass);
});
@@ -0,0 +1,7 @@
import { apiInitializer } from "discourse/lib/api";
export default apiInitializer("0.8.0", (api) => {
api.registerValueTransformer("bulk-select-in-nav-controls", () => {
return true;
});
});
@@ -0,0 +1,6 @@
import { apiInitializer } from "discourse/lib/api";
import SidebarNewTopicButton from "../components/sidebar-new-topic-button";
export default apiInitializer("1.8.0", (api) => {
api.renderInOutlet("before-sidebar-sections", SidebarNewTopicButton);
});
@@ -1,6 +0,0 @@
import { apiInitializer } from "discourse/lib/api";
import CustomUserPalette from "../components/custom-user-palette";
export default apiInitializer("1.8.0", (api) => {
api.renderInOutlet("sidebar-footer-actions", CustomUserPalette);
});
@@ -0,0 +1,59 @@
import Component from "@glimmer/component";
import concatClass from "discourse/helpers/concat-class";
import icon from "discourse/helpers/d-icon";
import formatDate from "discourse/helpers/format-date";
export default class TopicActivityColumn extends Component {
get topicUser() {
if (
moment(this.args.topic.bumped_at).isAfter(this.args.topic.last_posted_at)
) {
return {
user: undefined,
username: undefined,
activityText: "user_updated",
class: "--updated",
};
}
if (this.args.topic.posts_count > 1) {
return {
user: this.args.topic.lastPosterUser,
username: this.args.topic.last_poster_username,
activityText: "user_replied",
class: "--replied",
};
} else if (this.args.topic.posts_count === 1) {
return {
user: this.args.topic.firstPosterUser,
username: this.args.topic.last_poster_username,
class: "--created",
};
} else {
return;
}
}
<template>
<span class={{concatClass "topic-activity" this.topicUser.class}}>
<div class="topic-activity__type">
{{#if this.topicUser.user}}
{{icon "reply"}}
{{else}}
{{icon "pencil"}}
{{/if}}
</div>
{{#if this.topicUser.username}}
<span
class="topic-activity__username"
>{{this.topicUser.username}}</span>
<span class="dot-separator"></span>
{{/if}}
<div class="topic-activity__time">
{{formatDate @topic.bumpedAt leaveAgo="true" format="tiny"}}
</div>
</span>
</template>
}
@@ -1,9 +0,0 @@
import avatar from "discourse/helpers/avatar";
const TopicAuthorAvatarColumn = <template>
<span class="topic-author-avatar">
{{avatar @topic.creator imageSize="large"}}
</span>
</template>;
export default TopicAuthorAvatarColumn;
@@ -1,5 +0,0 @@
const TopicAuthorColumn = <template>
<span class="topic-author">@{{@topic.creator.username}}</span>
</template>;
export default TopicAuthorColumn;
@@ -0,0 +1,19 @@
import Component from "@glimmer/component";
import avatar from "discourse/helpers/avatar";
export default class TopicCreatorColumn extends Component {
get topicCreator() {
return {
user: this.args.topic.creator,
username: this.args.topic.creator.username,
class: "--topic-creator",
};
}
<template>
<div class={{this.topicUser.class}}>
{{avatar this.topicCreator.user}}
<span class="topic-creator__username">{{this.topicUser.username}}</span>
</div>
</template>
}
@@ -1,8 +1,8 @@
import { gt } from "truth-helpers";
import icon from "discourse/helpers/d-icon";
import gt from "truth-helpers/helpers/gt";
const TopicRepliesColumn = <template>
{{#if (gt @topic.posts_count 1)}}
{{#if (gt @topic.replyCount 1)}}
<span class="topic-replies">{{icon "reply"}}{{@topic.posts_count}}</span>
{{/if}}
</template>;
@@ -1,115 +1,36 @@
import Component from "@glimmer/component";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { and } from "truth-helpers";
import icon from "discourse/helpers/d-icon";
import { i18n } from "discourse-i18n";
export default class TopicStatusColumn extends Component {
@service currentUser;
@service siteSettings;
get canAct() {
return this.currentUser && !this.args.disableActions;
}
get statusClass() {
let classes = ["topic-status-card"];
if (this.args.topic.bookmarked) {
classes.push("--bookmark");
} else if (this.args.topic.closed && this.args.topic.archived) {
classes.push("--locked --archived");
} else if (this.args.topic.closed) {
classes.push("--locked");
} else if (this.args.topic.archived) {
classes.push("--archived");
} else if (this.args.topic.is_warning) {
classes.push("--warning");
} else if (
this.args.showPrivateMessageIcon &&
this.args.topic.isPrivateMessage
) {
classes.push("--private-message");
} else if (this.args.topic.pinned) {
classes.push("--pinned");
} else if (this.args.topic.unpinned) {
classes.push("--unpinned");
get badge() {
if (this.args.topic.is_hot) {
return {
icon: "fire",
text: "topic_hot",
className: "--hot",
};
}
return classes.join(" ");
}
get heatMap() {
return this.args.topic.views > this.siteSettings.topic_views_heat_medium;
}
if (this.args.topic.pinned) {
return {
icon: "thumbtack",
text: "topic_pinned",
className: "--pinned",
};
}
@action
togglePinned(event) {
event.preventDefault();
this.args.topic.togglePinnedForUser();
return null;
}
<template>
{{#if @topic.bookmarked}}
<span class={{this.statusClass}}>{{icon "bookmark"}}{{i18n
(themePrefix "topic_bookmarked")
}}</span>
{{/if}}
{{#if (and @topic.closed @topic.archived)~}}
<span class={{this.statusClass}}>{{i18n
(themePrefix "topic_closed_and_archived")
}}</span>
{{else if @topic.closed}}
<span class={{this.statusClass}}>{{i18n
(themePrefix "topic_closed")
}}</span>
{{else if @topic.archived}}
<span class={{this.statusClass}}>{{i18n
(themePrefix "topic_archived")
}}</span>
{{/if}}
{{#if @topic.is_warning}}
<span class={{this.statusClass}}>{{i18n
(themePrefix "topic_warning")
}}</span>
{{else if (and @showPrivateMessageIcon @topic.isPrivateMessage)}}
<span class={{this.statusClass}}>{{i18n
(themePrefix "topic_personal_message")
}}</span>
{{/if}}
{{#if @topic.pinned}}
{{#if this.canAct}}
<button
type="button"
{{on "click" this.togglePinned}}
class={{this.statusClass}}
>{{icon "thumbtack"}}{{i18n (themePrefix "topic_pinned")}}</button>
{{else}}
<span class={{this.statusClass}}>{{icon "thumbtack"}}{{i18n
(themePrefix "topic_pinned")
}}</span>
{{/if}}
{{else if @topic.unpinned}}
{{#if this.canAct}}
<button
type="button"
{{on "click" this.togglePinned}}
class={{this.statusClass}}
>{{icon "thumbtack" class="unpinned"}}{{i18n
(themePrefix "topic_unpinned")
}}</button>
{{else}}
<span class={{this.statusClass}}>{{icon
"thumbtack"
class="unpinned"
}}{{i18n (themePrefix "topic_unpinned")}}</span>
{{/if}}
{{/if}}
{{#if this.heatMap}}
<span class="topic-status-card --hot">{{icon "fire"}}{{i18n
(themePrefix "topic_hot")
}}</span>
{{#if this.badge}}
<span class="topic-status-card {{this.badge.className}}">{{icon
this.badge.icon
}}{{i18n (themePrefix this.badge.text)}}</span>
{{/if}}
</template>
}
@@ -0,0 +1,37 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import { service } from "@ember/service";
import DButton from "discourse/components/d-button";
import bodyClass from "discourse/helpers/body-class";
export default class ComposerPeekModeToggle extends Component {
@service composer;
@service keyValueStore;
@tracked
peekModeActive = this.keyValueStore.getItem("peekModeActive") === "true";
get bodyCssClass() {
return this.peekModeActive ? "peek-mode-active" : "";
}
@action
togglePeekMode() {
this.peekModeActive = !this.peekModeActive;
this.keyValueStore.setItem("peekModeActive", this.peekModeActive);
if (this.composer.showPreview) {
this.composer.togglePreview();
}
}
<template>
{{bodyClass this.bodyCssClass}}
<DButton
@action={{this.togglePeekMode}}
@preventFocus={{true}}
@icon="discourse-sidebar"
class="btn-mini-toggle no-text peek-mode-toggle btn-transparent"
/>
</template>
}
@@ -1,12 +0,0 @@
import Component from "@glimmer/component";
import { concat } from "@ember/helper";
import { service } from "@ember/service";
import htmlClass from "discourse/helpers/html-class";
export default class CustomColorHtmlClass extends Component {
@service customColor;
<template>
{{htmlClass (concat "custom-color-" this.customColor.color)}}
</template>
}
@@ -1,60 +0,0 @@
import icon from "discourse/helpers/d-icon";
import DMenu from "float-kit/components/d-menu";
import SitePaletteMenuItem from "./site-palette-menu-item";
const PALETTES = [
{
label: "Marigold",
name: "marigold",
color: "#d3881f",
},
{
label: "Violet",
name: "violet",
color: "#9b15de",
},
{
label: "Lily",
name: "lily",
color: "#CC336F",
},
{
label: "Clover",
name: "clover",
color: "#45a06e",
},
{
label: "Royal",
name: "royal",
color: "#4169e1",
},
{
label: "Horizon",
name: "horizon",
color: "#595bca",
},
];
export const DEFAULT_PALETTE_NAME = "horizon";
<template>
<DMenu
@identifier="user-color-palette"
@placementStrategy="fixed"
class="btn-flat user-color-palette sidebar-footer-actions-button"
@inline={{true}}
>
<:trigger>
{{icon "paintbrush"}}
</:trigger>
<:content>
<div class="color-palette-menu">
<div class="color-palette-menu__content">
{{#each PALETTES as |colorPalette|}}
<SitePaletteMenuItem @colorPalette={{colorPalette}} />
{{/each}}
</div>
</div>
</:content>
</DMenu>
</template>
@@ -2,10 +2,15 @@ import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
import { service } from "@ember/service";
import { htmlSafe } from "@ember/template";
import { bind } from "discourse/lib/decorators";
const DO_NOT_RENDER_LIST = ["login"];
export default class ExperimentalScreen extends Component {
@service router;
@tracked left = 0;
@tracked right = 0;
resizeObserver;
@@ -28,6 +33,10 @@ export default class ExperimentalScreen extends Component {
);
}
get shouldRender() {
return !DO_NOT_RENDER_LIST.includes(this.router.currentRouteName);
}
@action
onInsert(element) {
this.calculateDistance(element);
@@ -42,16 +51,18 @@ export default class ExperimentalScreen extends Component {
}
<template>
<ul
class="experimental-screen"
{{didInsert this.onInsert}}
style={{this.distanceStyles}}
>
<li class="experimental-screen__top-left"></li>
<li class="experimental-screen__top-right"></li>
<li class="experimental-screen__bottom-left"></li>
<li class="experimental-screen__bottom-right"></li>
<li class="experimental-screen__bottom-bar"></li>
</ul>
{{#if this.shouldRender}}
<ul
class="experimental-screen"
{{didInsert this.onInsert}}
style={{this.distanceStyles}}
>
<li class="experimental-screen__top-left"></li>
<li class="experimental-screen__top-right"></li>
<li class="experimental-screen__bottom-left"></li>
<li class="experimental-screen__bottom-right"></li>
<li class="experimental-screen__bottom-bar"></li>
</ul>
{{/if}}
</template>
}
@@ -0,0 +1,116 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
import didUpdate from "@ember/render-modifiers/modifiers/did-update";
import willDestroy from "@ember/render-modifiers/modifiers/will-destroy";
import { service } from "@ember/service";
import { gt, not } from "truth-helpers";
import CreateTopicButton from "discourse/components/create-topic-button";
export default class SidebarNewTopicButton extends Component {
@service composer;
@service currentUser;
@service siteSettings;
@service router;
@service header;
@service appEvents;
@tracked category;
@tracked tag;
get shouldRender() {
return this.currentUser && !this.router.currentRouteName.includes("admin");
}
get canCreateTopic() {
return this.currentUser?.can_create_topic;
}
get draftCount() {
return this.currentUser?.get("draft_count");
}
get createTopicTargetCategory() {
if (this.category?.canCreateTopic) {
return this.category;
}
if (this.siteSettings.default_subcategory_on_read_only_category) {
return this.category?.subcategoryWithCreateTopicPermission;
}
}
get tagRestricted() {
return this.tag?.staff;
}
get createTopicDisabled() {
return (
(this.category && !this.createTopicTargetCategory) ||
(this.tagRestricted && !this.currentUser.staff)
);
}
get categoryReadOnlyBanner() {
if (this.category && this.currentUser && this.createTopicDisabled) {
return this.category.read_only_banner;
}
}
get createTopicClass() {
const baseClasses = "btn-default sidebar-new-topic-button";
return this.categoryReadOnlyBanner
? `${baseClasses} disabled`
: baseClasses;
}
@action
createNewTopic() {
this.composer.openNewTopic({ category: this.category, tags: this.tag?.id });
}
@action
getCategoryandTag() {
this.category = this.router.currentRoute.attributes?.category || null;
this.tag = this.router.currentRoute.attributes?.tag || null;
}
@action
watchForComposer() {
// this covers opening drafts from the hamburger menu
this.appEvents.on("composer:will-open", this, this.closeHamburger);
}
@action
stopWatchingForComposer() {
this.appEvents.off("composer:will-open", this, this.closeHamburger);
}
@action
closeHamburger() {
this.header.hamburgerVisible = false;
}
<template>
{{#if this.shouldRender}}
<div
class="sidebar-new-topic-button__wrapper"
{{didInsert this.getCategoryandTag}}
{{didUpdate this.getCategoryandTag this.router.currentRoute}}
{{didInsert this.watchForComposer}}
{{willDestroy this.stopWatchingForComposer}}
>
<CreateTopicButton
@canCreateTopic={{this.canCreateTopic}}
@action={{this.createNewTopic}}
@disabled={{this.createTopicDisabled}}
@label="topic.create"
@btnClass={{this.createTopicClass}}
@canCreateTopicOnTag={{not this.tagRestricted}}
@showDrafts={{gt this.draftCount 0}}
/>
</div>
{{/if}}
</template>
}
@@ -1,40 +1,43 @@
import Component from "@glimmer/component";
import { fn } from "@ember/helper";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { htmlSafe } from "@ember/template";
import DButton from "discourse/components/d-button";
import concatClass from "discourse/helpers/concat-class";
export default class SitePaletteMenuItem extends Component {
@service customColor;
export default class UserColorPaletteMenuItem extends Component {
@service site;
@service session;
get siteStyle() {
return `--icon-color: ${this.args.colorPalette.color}`;
return `--icon-color: ${this.args.colorPalette.accent}`;
}
get activeClass() {
if (this.customColor.color === this.args.colorPalette.name) {
if (this.args.selectedColorPaletteId === this.args.colorPalette.id) {
return "active";
}
}
@action
handleInput(colorPalette) {
this.customColor.setColor(colorPalette.name);
paletteSelected() {
this.args.paletteSelected(this.args.colorPalette);
}
<template>
<div class="color-palette-menu__item" data-color={{@colorPalette.name}}>
<div
class="user-color-palette-menu__item"
data-color-palette={{@colorPalette.name}}
>
<DButton
class={{concatClass
"btn-flat color-palette-menu__item-choice"
"btn-flat user-color-palette-menu__item-choice"
this.activeClass
}}
style={{htmlSafe this.siteStyle}}
@icon="circle"
@translatedLabel={{@colorPalette.label}}
@action={{fn this.handleInput @colorPalette}}
@translatedLabel={{@colorPalette.name}}
@action={{this.paletteSelected}}
/>
</div>
</template>
@@ -0,0 +1,210 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { isEmpty } from "@ember/utils";
import { Promise } from "rsvp";
import concatClass from "discourse/helpers/concat-class";
import icon from "discourse/helpers/d-icon";
import { reload } from "discourse/helpers/page-reloader";
import { ajax } from "discourse/lib/ajax";
import {
listColorSchemes,
updateColorSchemeCookie,
} from "discourse/lib/color-scheme-picker";
import cookie from "discourse/lib/cookie";
import DMenu from "float-kit/components/d-menu";
import UserColorPaletteMenuItem from "./user-color-palette-menu-item";
const HORIZON_PALETTES = [
"Horizon",
"Marigold",
"Violet",
"Lily",
"Clover",
"Royal",
];
export default class UserColorPaletteSelector extends Component {
@service currentUser;
@service keyValueStore;
@service site;
@service session;
@service interfaceColor;
@tracked anonColorPaletteId = this.#loadAnonColorPalette();
@tracked userColorPaletteId = this.session.userColorSchemeId;
@tracked cssLoaded = true;
get userColorPalettes() {
const availablePalettes = listColorSchemes(this.site)
?.map((userPalette) => {
return {
...userPalette,
accent: `#${
userPalette.colors.find((color) => color.name === "tertiary").hex
}`,
};
})
.filter((userPalette) => {
return HORIZON_PALETTES.some((palette) => {
return userPalette.name.toLowerCase().includes(palette.toLowerCase());
});
})
.sort();
// Match the light scheme with the corresponding dark id based in the name
return (
availablePalettes
?.map((palette) => {
if (palette.is_dark) {
return palette;
}
const normalizedLightName = palette.name.toLowerCase();
const correspondingDarkModeId = availablePalettes.find(
(item) =>
item.is_dark &&
normalizedLightName ===
item.name.toLowerCase().replace(/\s+dark$/, "")
)?.id;
return {
...palette,
correspondingDarkModeId,
};
})
// Only want to show palettes that have corresponding light/dark modes
.filter((palette) => !palette.is_dark)
);
}
get selectedColorPaletteId() {
if (this.currentUser) {
return this.userColorPaletteId;
}
return this.anonColorPaletteId;
}
@action
onRegisterMenu(api) {
this.dMenu = api;
}
@action
paletteSelected(selectedPalette) {
if (selectedPalette.id === this.selectedColorPaletteId) {
return;
}
this.#updatePreference(selectedPalette);
this.#changeSiteColorPalette(selectedPalette);
this.dMenu.close();
}
#updatePreference(selectedPalette) {
updateColorSchemeCookie(selectedPalette.id);
updateColorSchemeCookie(selectedPalette.correspondingDarkModeId, {
dark: true,
});
if (!this.currentUser) {
this.anonColorPaletteId = selectedPalette.id;
} else {
this.userColorPaletteId = selectedPalette.id;
}
}
#loadAnonColorPalette() {
const storedAnonPaletteId = cookie("color_scheme_id");
if (storedAnonPaletteId) {
return parseInt(storedAnonPaletteId, 10);
}
}
async #changeSiteColorPalette(colorPalette) {
this.cssLoaded = false;
const lightPaletteId = colorPalette.id;
const darkPaletteId = colorPalette.correspondingDarkModeId;
const darkTag = document.querySelector("link.dark-scheme");
// TODO(osama) once we have built-in light/dark modes for each palette, we
// can stop making the 2nd ajax call for the dark palette and replace it
// with a include_dark_scheme param on the ajax call for the light
// palette which will include the href for the dark palette in the response
if (!darkTag) {
reload();
return;
}
const lightPaletteInfo = await ajax(
`/color-scheme-stylesheet/${lightPaletteId}/${colorPalette.theme_id}.json`
);
const darkPaletteInfo = await ajax(
`/color-scheme-stylesheet/${darkPaletteId}/${colorPalette.theme_id}.json`
);
Promise.all([
this.#preloadAndSwapCSS(lightPaletteInfo.new_href, "light-scheme"),
this.#preloadAndSwapCSS(darkPaletteInfo.new_href, "dark-scheme"),
]).then(() => {
this.cssLoaded = true;
});
}
#preloadAndSwapCSS(newHref, existingLinkClass) {
return new Promise((resolve) => {
const existingLink = document.querySelector(
`link[rel='stylesheet'].${existingLinkClass}`
);
const newTag = document.createElement("link");
newTag.rel = "preload";
newTag.href = newHref;
newTag.as = "style";
newTag.onload = () => {
existingLink.href = newHref;
newTag.remove();
resolve();
};
document.head.appendChild(newTag);
});
}
<template>
{{#unless (isEmpty this.userColorPalettes)}}
<DMenu
@identifier="user-color-palette-selector"
@placementStrategy="fixed"
@onRegisterApi={{this.onRegisterMenu}}
class={{concatClass
"btn-flat user-color-palette-selector sidebar-footer-actions-button"
(if this.cssLoaded "user-color-palette-css-loaded")
}}
data-selected-color-palette-id={{this.selectedColorPaletteId}}
@inline={{true}}
>
<:trigger>
{{icon "paintbrush"}}
</:trigger>
<:content>
<div class="user-color-palette-menu">
<div class="user-color-palette-menu__content">
{{#each this.userColorPalettes as |colorPalette|}}
<UserColorPaletteMenuItem
@selectedColorPaletteId={{this.selectedColorPaletteId}}
@colorPalette={{colorPalette}}
@paletteSelected={{this.paletteSelected}}
/>
{{/each}}
</div>
</div>
</:content>
</DMenu>
{{/unless}}
</template>
}
@@ -1,30 +1,29 @@
import { withPluginApi } from "discourse/lib/plugin-api";
import TopicAuthorAvatarColumn from "../components/card/topic-author-avatar-column";
import TopicAuthorColumn from "../components/card/topic-author-column";
import TopicActivityColumn from "../components/card/topic-activity-column";
import TopicCategoryColumn from "../components/card/topic-category-column";
import TopicCreatorColumn from "../components/card/topic-creator-column";
import TopicLikesColumn from "../components/card/topic-likes-column";
import TopicRepliesColumn from "../components/card/topic-replies-column";
import TopicStatusColumn from "../components/card/topic-status-column";
const TopicAuthor = <template>
<td class="topic-author-data">
<TopicAuthorColumn @topic={{@topic}} />
const TopicActivity = <template>
<td class="topic-activity-data">
<TopicActivityColumn @topic={{@topic}} />
</td>
</template>;
const TopicAuthorAvatar = <template>
<td class="topic-author-avatar-data">
<TopicAuthorAvatarColumn @topic={{@topic}} />
</td>
</template>;
const TopicCategoryStatus = <template>
<td class="topic-category-status-data">
<TopicCategoryColumn @topic={{@topic}} />
const TopicStatus = <template>
<td class="topic-status-data">
<TopicStatusColumn @topic={{@topic}} />
</td>
</template>;
const TopicCategory = <template>
<td class="topic-category-data">
<TopicCategoryColumn @topic={{@topic}} />
</td>
</template>;
const TopicLikesReplies = <template>
<td class="topic-likes-replies-data">
<TopicLikesColumn @topic={{@topic}} />
@@ -32,33 +31,48 @@ const TopicLikesReplies = <template>
</td>
</template>;
const TopicCreator = <template>
<td class="topic-creator-data">
<TopicCreatorColumn @topic={{@topic}} />
</td>
</template>;
export default {
name: "topic-list-customizations",
initialize() {
initialize(container) {
const router = container.lookup("service:router");
withPluginApi("1.39.0", (api) => {
api.registerValueTransformer(
"topic-list-columns",
({ value: columns }) => {
columns.add("topic-author", {
item: TopicAuthor,
after: "activity",
});
columns.add("topic-category-status", {
item: TopicCategoryStatus,
columns.add("topic-status", {
item: TopicStatus,
after: "topic-author",
});
columns.add("topic-author-avatar", {
item: TopicAuthorAvatar,
after: "topic-category-status",
columns.add("topic-category", {
item: TopicCategory,
after: "topic-status",
});
columns.add("topic-likes-replies", {
item: TopicLikesReplies,
after: "topic-author-avatar",
});
columns.delete("posters");
columns.add("topic-creator", {
item: TopicCreator,
after: "topic-author-avatar",
});
columns.delete("views");
columns.delete("replies");
if (!router.currentRouteName.includes("userPrivateMessages")) {
columns.add("topic-activity", {
item: TopicActivity,
after: "title",
});
columns.delete("posters");
columns.delete("activity");
}
return columns;
}
);
@@ -66,8 +80,12 @@ export default {
api.registerValueTransformer(
"topic-list-item-class",
({ value: classes, context }) => {
if (context.topic.pinned || context.topic.pinned_globally) {
classes.push("--pinned");
if (
context.topic.is_hot ||
context.topic.pinned ||
context.topic.pinned_globally
) {
classes.push("--has-status-card");
}
return classes;
}
@@ -76,6 +94,34 @@ export default {
api.registerValueTransformer("topic-list-item-mobile-layout", () => {
return false;
});
api.registerBehaviorTransformer(
"topic-list-item-click",
({ context: { event }, next }) => {
if (event.target.closest("a, button, input")) {
return next();
}
event.preventDefault();
event.stopPropagation();
const topicLink = event.target
.closest("tr")
.querySelector("a.raw-topic-link");
// Redespatch the click on the topic link, so that all key-handing is sorted
topicLink.dispatchEvent(
new MouseEvent("click", {
ctrlKey: event.ctrlKey,
metaKey: event.metaKey,
shiftKey: event.shiftKey,
button: event.button,
bubbles: true,
cancelable: true,
})
);
}
);
});
},
};
@@ -1,18 +0,0 @@
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import Service, { service } from "@ember/service";
import { DEFAULT_PALETTE_NAME } from "../components/custom-user-palette";
const CUSTOM_COLOR_KEY = "d-custom-color-preference";
export default class CustomColor extends Service {
@service keyValueStore;
@tracked
color = this.keyValueStore.getItem(CUSTOM_COLOR_KEY) || DEFAULT_PALETTE_NAME;
@action
setColor(color) {
this.color = color;
this.keyValueStore.setItem(CUSTOM_COLOR_KEY, color);
}
}
+3 -7
View File
@@ -1,12 +1,8 @@
en:
theme_metadata:
description: "A simple, beautiful theme that improves the out of the box experience for Discourse sites."
topic_bookmarked: "Bookmarked"
topic_closed_archived: "Closed and archived"
topic_closed: "Closed"
topic_archived: "Archived"
topic_warning: "Warning"
topic_personal_message: "Personal message"
topic_pinned: "Pinned"
topic_unpinned: "Unpinned"
topic_hot: "Hot"
user_replied: "replied"
user_posted: "posted"
user_updated: "updated"
+6 -5
View File
@@ -1,13 +1,14 @@
{
"private": true,
"devDependencies": {
"@discourse/lint-configs": "2.4.0",
"ember-template-lint": "6.1.0",
"eslint": "9.19.0",
"prettier": "2.8.8"
"@discourse/lint-configs": "2.25.0",
"ember-template-lint": "7.8.1",
"eslint": "9.28.0",
"prettier": "3.5.3",
"stylelint": "16.20.0"
},
"engines": {
"node": ">= 18",
"node": ">= 22",
"npm": "please-use-pnpm",
"yarn": "please-use-pnpm",
"pnpm": "9.x"
+1089 -1770
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

View File
+72 -22
View File
@@ -1,4 +1,6 @@
@media screen and (min-width: 1300px) {
@use "lib/viewport";
@media screen and (width >= 1300px) {
#main-outlet {
border-top-right-radius: var(--d-border-radius-large);
border-top-left-radius: var(--d-border-radius-large);
@@ -18,38 +20,47 @@
}
.has-full-page-chat .chat-replying-indicator-container {
margin-bottom: var(--d-border-radius-large);
@include breakpoint(medium) {
margin-bottom: var(--main-grid-gap);
@include viewport.until(lg) {
margin-bottom: 0;
}
}
.has-full-page-chat .chat-selection-management {
margin-bottom: var(--d-border-radius-large);
@include breakpoint(medium) {
margin-bottom: var(--main-grid-gap);
@include viewport.until(lg) {
margin-bottom: 0;
}
}
.experimental-screen {
@include breakpoint(medium) {
display: none;
}
max-width: unset !important;
@media screen and (max-width: 488px) {
display: none;
}
width: 100%;
display: block;
margin: 0;
padding: 0;
position: relative;
container: content-width / inline-size;
@include viewport.until(lg) {
display: none;
}
@media screen and (width <= 488px) {
display: none;
}
@include viewport.until(md) {
display: none;
}
li {
list-style: none;
margin: 0;
padding: 0;
}
&__top-left,
&__top-right,
&__bottom-left,
@@ -59,38 +70,45 @@
height: var(--d-border-radius-large);
background-color: var(--background-color);
z-index: 399;
-webkit-mask: radial-gradient(
mask: radial-gradient(
circle at var(--d-border-radius-large) var(--d-border-radius-large),
transparent var(--d-border-radius-large),
transparent var(--d-border-radius-large),
black var(--d-border-radius-large)
);
}
&__top-left {
top: var(--header-offset);
left: var(--left-distance);
}
&__top-right {
top: var(--header-offset);
transform: rotate(90deg);
left: calc(var(--right-distance) - var(--d-border-radius-large));
}
&__bottom-left {
transform: rotate(-90deg);
bottom: var(--d-border-radius-large);
bottom: var(--main-grid-gap);
left: var(--left-distance);
@media screen and (max-width: 768px) {
@media screen and (width <= 768px) {
bottom: calc(var(--d-border-radius-large) * 2);
}
}
&__bottom-right {
transform: rotate(180deg);
bottom: var(--d-border-radius-large);
bottom: var(--main-grid-gap);
left: calc(var(--right-distance) - var(--d-border-radius-large));
@media screen and (max-width: 768px) {
@media screen and (width <= 768px) {
bottom: calc(var(--d-border-radius-large) * 2);
}
}
&__bottom-bar {
position: fixed;
width: 100%;
@@ -98,17 +116,49 @@
background-color: var(--background-color);
bottom: 0;
left: var(--left-distance);
height: var(--d-border-radius-large);
@media screen and (max-width: 768px) {
height: var(--main-grid-gap);
@media screen and (width <= 768px) {
height: calc(var(--d-border-radius-large) * 2);
}
@container content-width (width > 1px) {
width: 100cqw;
}
}
}
@media screen and (min-width: 768px) {
.rtl .experimental-screen {
&__top-left {
right: var(--left-distance);
left: unset;
}
&__top-right {
transform: rotate(-90deg) !important;
right: calc(var(--right-distance) - var(--d-border-radius-large));
left: unset;
}
&__bottom-left {
transform: rotate(90deg);
right: var(--left-distance);
left: unset;
}
&__bottom-right {
transform: rotate(180deg);
left: unset;
right: calc(var(--right-distance) - var(--d-border-radius-large));
}
&__bottom-bar {
right: var(--left-distance);
left: unset;
}
}
@media screen and (width >= 768px) {
.with-topic-progress {
bottom: calc(
env(safe-area-inset-bottom) + var(--composer-height, 0px) +
@@ -117,7 +167,7 @@
}
}
@media screen and (max-width: 768px) {
@media screen and (width <= 768px) {
.with-topic-progress {
bottom: calc(
env(safe-area-inset-bottom) + var(--composer-height, 0px) +
@@ -126,7 +176,7 @@
}
}
@media screen and (max-width: 400px) {
@media screen and (width <= 400px) {
.with-topic-progress {
bottom: calc(env(safe-area-inset-bottom) + var(--composer-height, 0px));
}
+31 -8
View File
@@ -8,11 +8,13 @@
.sidebar-new-topic-button__wrapper .topic-drafts-menu-trigger.btn.no-text {
background: var(--accent-color);
&:hover,
&:focus-visible {
background: oklch(from var(--accent-color) 40% c h) !important;
box-shadow: none;
}
.d-icon {
color: var(--accent-text-color);
}
@@ -26,31 +28,37 @@
.discourse-no-touch .btn-default,
.discourse-no-touch .select-kit .select-kit-header.btn-default {
background: var(--primary-100);
.d-icon {
color: var(--accent-color);
}
&:hover {
border-color: transparent;
box-shadow: 0px 0px 8px 1px var(--button-box-shadow);
box-shadow: 0 0 8px 1px var(--button-box-shadow);
background: var(--d-content-background);
color: var(--accent-color);
.d-icon {
color: var(--accent-color);
}
}
&:focus-visible {
background: var(--d-content-background);
color: var(--accent-color);
box-shadow: 0px 0px 0px 3px var(--button-box-shadow);
box-shadow: 0 0 0 3px var(--button-box-shadow);
.d-icon {
color: var(--accent-color);
}
}
&:active:not(:hover, :focus) {
color: var(--primary);
background: var(--tertiary-300);
background-image: none;
.d-icon {
color: var(--tertiary-high);
}
@@ -58,30 +66,45 @@
}
.btn-primary,
#create-topic.btn {
#create-topic.btn,
.discourse-no-touch .btn-default.ai-new-question-button {
background-color: var(--accent-color);
color: var(--accent-text-color);
.d-icon {
color: var(--accent-text-color);
}
&:hover {
.discourse-no-touch & {
background: oklch(from var(--accent-color) 40% c h) !important;
box-shadow: 0px 0px 6px 1px var(--button-box-shadow);
background: light-dark(
oklch(from var(--accent-color) 40% c h),
oklch(from var(--accent-color) 50% c h)
);
box-shadow: 0 0 6px 1px var(--button-box-shadow);
color: var(--accent-text-color);
.d-icon {
color: var(--accent-text-color);
}
}
}
&:focus-visible {
.discourse-no-touch & {
background: oklch(from var(--accent-color) 40% c h) !important;
box-shadow: 0px 0px 0px 4px var(--button-box-shadow);
background: light-dark(
oklch(from var(--accent-color) 40% c h),
oklch(from var(--accent-color) 50% c h)
);
box-shadow: 0 0 0 4px var(--button-box-shadow);
color: var(--accent-text-color);
}
}
&:active {
background: oklch(from var(--accent-color) 30% c h) !important;
background: light-dark(
oklch(from var(--accent-color) 40% c h),
oklch(from var(--accent-color) 50% c h)
);
}
}
+38 -3
View File
@@ -1,9 +1,13 @@
@use "lib/viewport";
.full-page-chat.full-page-chat-sidebar-enabled {
border: none;
}
.c-navbar-container {
padding: 0 1.5em;
.full-page-chat & {
padding: 0 1.5em;
}
background-color: var(--d-content-background);
}
@@ -13,22 +17,43 @@ body.has-full-page-chat {
.chat-drawer-container {
.is-expanded & {
box-shadow: 0px 0px 0px 2px var(--d-chat-border);
box-shadow: 0 0 0 2px var(--tertiary-medium);
}
.chat-drawer.is-expanded & {
border: none;
}
.c-navbar__title {
padding-left: 0.33em; // visual alignment for chat index, which does not havea a backarrow
}
}
.chat-drawer-outlet-container {
z-index: z("composer", "content");
.peek-mode-active & {
padding-bottom: 0;
left: unset;
right: var(--main-grid-gap);
&:has(.is-expanded) {
z-index: calc(z("composer", "dropdown") + 1);
}
}
}
.chat-drawer {
.peek-mode-active & {
max-width: 90vw;
}
}
.chat-drawer .channels-list-container .chat-channel-row {
margin-bottom: var(--spacing-block-xs);
font-size: var(--font-up-1);
border-radius: var(--d-border-radius);
border-bottom: none;
&:hover {
background-color: var(--d-sidebar-active-background);
}
@@ -51,3 +76,13 @@ body.has-full-page-chat {
color: var(--primary);
}
}
.chat-drawer-active.chat-drawer-expanded .chat-composer-dropdown__menu-content {
z-index: z("modal", "dialog");
}
.chat-replying-indicator-container {
@include viewport.from(sm) {
margin-left: calc(0.65em + 0.2rem);
}
}
+5 -25
View File
@@ -1,20 +1,24 @@
.color-palette-menu {
.user-color-palette-menu {
&__item .btn-icon-text.btn-flat {
background-color: var(--d-content-background);
width: 100%;
justify-content: flex-start;
}
&__item .btn-icon-text.btn-flat:hover {
background-color: var(--d-selected);
box-shadow: none;
color: var(--primary);
}
&__item .btn-icon-text.btn-flat:hover svg {
color: var(--icon-color);
}
&__item .btn-icon-text.btn-flat svg {
color: var(--icon-color);
}
&__item-choice.active.btn-icon-text.btn-flat {
background-color: var(--d-selected);
}
@@ -23,27 +27,3 @@
.user-color-palette-content .fk-d-menu__inner-content {
border: none;
}
html.custom-color-horizon {
--accent-base-color: #595bca;
}
html.custom-color-marigold {
--accent-base-color: #d3881f;
}
html.custom-color-violet {
--accent-base-color: #9b15de;
}
html.custom-color-lily {
--accent-base-color: #cc338c;
}
html.custom-color-clover {
--accent-base-color: #45a06e;
}
html.custom-color-royal {
--accent-base-color: #4169e1;
}
+4 -99
View File
@@ -1,108 +1,12 @@
:root {
--accent-base-color: #595bca;
--accent-color: light-dark(
var(--accent-base-color),
oklch(from var(--accent-base-color) calc(l * 0.95) c h)
);
// --background-color: light-dark(#f5f8ff, #101112);
--background-color: light-dark(
oklch(from var(--accent-color) 98% calc(c * 0.25) h),
oklch(from var(--accent-color) 10% 0.025 h)
);
--header_primary-low-mid: light-dark(
oklch(from var(--background-color) calc(l * 0.75) calc(c * 2) h),
oklch(from var(--accent-color) calc(l * 1) calc(c * 0.25) h)
);
--header_primary-medium: light-dark(
oklch(from var(--background-color) calc(l * 0.55) calc(c * 2) h),
oklch(from var(--accent-color) calc(l * 1.35) calc(c * 0.25) h)
);
--d-content-background: light-dark(
oklch(from var(--accent-color) calc(l * 2) 0 h),
oklch(from var(--accent-color) calc(l * 0.375) 0 h)
);
--primary-100: light-dark(#f2f2f2, #333333);
--primary-300: light-dark(#d1d1d1, #838383);
--primary-low: light-dark(#e9e9e9, #313131);
--primary-high: light-dark(#646464, #a6a6a6);
--primary-very-high: light-dark(#434343, #c7c7c7);
--d-hover: oklch(from var(--d-selected) l c h / 0.75);
--tertiary: var(--accent-color);
--tertiary-medium: light-dark(
oklch(from var(--accent-color) calc(l * 1.25) calc(c * 0.25) h),
oklch(from var(--accent-color) calc(l * 0.75) calc(c * 0.25) h)
);
--tertiary-very-low: light-dark(
oklch(from var(--accent-color) calc(l * 1.75) calc(c * 0.25) h),
oklch(from var(--accent-color) calc(l * 0.5) calc(c * 0.25) h)
);
--tertiary-med-or-tertiary: var(--accent-color);
--tertiary-low: light-dark(
oklch(from var(--accent-color) calc(l * 1.6) calc(c * 0.25) h),
oklch(from var(--accent-color) calc(l * 0.6) calc(c * 0.25) h)
);
--tertiary-300: light-dark(
oklch(from var(--accent-color) calc(l * 1.5) calc(c * 2) h),
oklch(from var(--accent-color) calc(l * 0.65) calc(c * 0.65) h)
);
--tertiary-high: light-dark(
oklch(from var(--accent-color) calc(l * 1) c h),
oklch(from var(--accent-color) calc(l * 1) c h)
);
--d-sidebar-highlight-hover-icon: var(--d-sidebar-link-color);
--search-color: light-dark(
oklch(from var(--accent-color) calc(l * 0.65) calc(c * 0.65) h),
oklch(from var(--accent-color) calc(l * 1.5) calc(c * 2) h)
);
--search-banner-text-color: light-dark(
oklch(from var(--accent-color) calc(l * 0.65) calc(c * 0.65) h),
oklch(from var(--accent-color) calc(l * 1.85) calc(c * 2) h)
);
--topic-card-shadow: light-dark(
oklch(from var(--accent-color) calc(l * 1.85) calc(c * 0.5) h),
oklch(from var(--accent-color) calc(l * 0.2) calc(c * 0.01) h / 0.25)
);
--button-box-shadow: light-dark(
oklch(from var(--accent-color) calc(l * 1.5) calc(c * 0.35) h),
oklch(from var(--accent-color) calc(l * 0.75) calc(c * 0.5) h)
);
--d-selected: light-dark(
oklch(from var(--background-color) calc(l * 0.9375) calc(c * 2) h),
oklch(from var(--accent-color) calc(l * 0.7) calc(c * 0.25) h)
);
--d-sidebar-highlight-hover-background: var(--d-selected);
--d-sidebar-border-color: light-dark(
oklch(from var(--background-color) calc(l * 0.9) calc(c * 1) h),
oklch(from var(--accent-color) calc(l * 0.7) calc(c * 0.25) h)
);
--d-chat-border: light-dark(
oklch(from var(--accent-color) calc(l * 1.25) calc(c * 0.25) h),
oklch(from var(--accent-color) calc(l * 0.25) calc(c * 0.25) h)
);
--accent-text-color: light-dark(#ffffff, #212121);
--d-nav-color--active: var(--accent-color);
--d-sidebar-background: var(--background-color);
--d-sidebar-footer-fade: rgba(var(--tertiary-50-rgb), 1);
--d-sidebar-link-color: light-dark(
oklch(from var(--accent-color) calc(l * 0.8) calc(c * 0.25) h),
oklch(from var(--accent-color) calc(l * 1.5) calc(c * 0.25) h)
);
--d-sidebar-link-icon-color: var(--d-sidebar-link-color);
--d-sidebar-header-color: var(--d-sidebar-link-color);
--d-sidebar-header-icon-color: var(--d-sidebar-link-color);
--d-sidebar-suffix-color: light-dark(
oklch(from var(--accent-base-color) calc(l * 1) calc(c * 0.9) h),
oklch(from var(--accent-base-color) calc(l * 1) calc(c * 0.9) h)
);
--d-sidebar-active-suffix-color: var(--d-sidebar-suffix-color);
--link-color: light-dark(
var(--accent-base-color),
oklch(from var(--accent-base-color) calc(l * 0.95) c h)
);
--link-color-hover: light-dark(
var(--accent-base-color),
oklch(from var(--accent-base-color) calc(l * 1.5) calc(c * 2.25) h)
);
--d-sidebar-background: var(--background-color);
--d-sidebar-footer-fade: rgb(var(--tertiary-50-rgb), 1);
--d-sidebar-prefix-background: var(--d-selected);
--d-sidebar-active-prefix-background: light-dark(
oklch(from var(--d-selected) calc(l * 0.85) c h),
@@ -116,6 +20,7 @@
--d-sidebar-highlight-color: var(--primary);
--d-sidebar-highlight-background: var(--d-selected);
--d-sidebar-section-link-icon-size: 1em;
--d-hover: oklch(from var(--d-selected) l c h / 0.75);
--d-input-bg-color: var(--d-content-background);
--tertiary-hover: var(--accent-color);
--d-sidebar-active-color: var(--primary) !important;
}
+65
View File
@@ -0,0 +1,65 @@
.peek-mode-toggle {
display: none;
}
@media screen and (width >= 1300px) {
html:not(.fullscreen-composer) {
.peek-mode-toggle svg {
transform: scaleX(-1);
}
&.composer-open {
.full-width-enabled .peek-mode-toggle {
display: flex;
}
.full-width-enabled.peek-mode-active {
#reply-control.hide-preview {
transition: none;
box-shadow: none;
border-radius: var(--d-border-radius-large);
.grippie {
display: none;
}
.reply-area {
padding-inline: 0.67em;
}
}
#reply-control:not(.fullscreen).hide-preview {
width: 100%;
right: var(--main-grid-gap);
top: var(--header-offset);
bottom: var(--main-grid-gap);
left: unset;
height: unset;
max-width: 36.5vw;
}
&.has-sidebar-page {
#main-outlet-wrapper {
grid-template-columns:
var(--d-sidebar-width) calc(100vw - 38vw - var(--d-sidebar-width))
1fr;
}
}
&:not(.has-sidebar-page) {
#main-outlet-wrapper {
grid-template-columns: 0 calc(100vw - 52vw) 1fr;
}
#reply-control:not(.fullscreen).hide-preview {
max-width: 46vw;
}
}
.sidebar-wrapper .sidebar-container {
height: unset;
}
}
}
}
}
+82 -1
View File
@@ -1,14 +1,70 @@
@use "lib/viewport";
#reply-control
.select-kit.dropdown-select-box.composer-actions
.select-kit-header {
border: 1px solid var(--tertiary-700);
background: var(--secondary);
&:hover {
.d-icon {
color: var(--accent-color);
}
}
}
#reply-control.hide-preview:not(.draft) {
@include viewport.from(sm) {
background: var(--d-content-background);
border-top-right-radius: var(--d-border-radius);
border-top-left-radius: var(--d-border-radius);
.grippie {
background: var(--tertiary-low);
border-top-right-radius: var(--d-border-radius);
border-top-left-radius: var(--d-border-radius);
}
.user-selector,
.title-and-category {
padding: 0 var(--spacing-inline-m);
width: calc(100% - var(--spacing-inline-m) * 2);
}
.d-editor-button-bar {
padding: 3px var(--spacing-inline-m);
border: none;
}
.d-editor-input {
padding: var(--spacing-inline-m);
}
&:has(.in-focus) .grippie {
background: var(--tertiary);
}
.reply-area {
padding-inline: 0;
}
.reply-to,
.submit-panel {
padding-inline: var(--spacing-inline-sm);
}
.d-editor-textarea-wrapper {
border: 0;
border-bottom: 1px solid var(--primary-low);
border-radius: 0;
&.in-focus {
outline: 0;
}
}
}
}
.d-editor-button-bar {
.btn:hover,
.toolbar-popup-menu-options.is-expanded {
@@ -20,11 +76,12 @@
color: inherit;
}
//to have parity with regular select-kit styling used elsewhere
// to have parity with regular select-kit styling used elsewhere
.select-kit-row {
.d-icon {
color: var(--primary-high);
}
&:hover {
.d-icon {
color: var(--primary);
@@ -38,3 +95,27 @@
border-radius: var(--d-border-radius);
}
}
.discourse-no-touch .translation-selector-dropdown {
.select-kit-header.btn-default {
background: var(--background-color);
}
}
#reply-control.composer-action-add_translation {
.d-editor-preview .d-editor-translation-preview-wrapper {
border-color: var(--d-sidebar-border-color);
}
.d-editor-preview .d-editor-translation-preview-wrapper__header {
top: 6.5rem;
padding: 0.25rem 0.75rem;
background: var(--background-color);
color: var(--accent-color);
border-radius: var(--d-border-radius-large);
}
.topic-title-translator input {
width: 47.25vw;
}
}
+276
View File
@@ -0,0 +1,276 @@
@use "lib/viewport";
// Full width layout. Ported from the Discourse Full Width theme component here
// https://meta.discourse.org/t/discourse-full-width-component/292496, which we
// intend to move into core over time.
//
// We are copying this here so we can continue to iterate on Horizon with full
// width without having to include the theme component as a dependency, we
// need to remove this once full width is in core.
$sidebar-width: 17em;
.wrap {
max-width: unset; // undoing core default
}
.d-header #site-logo {
// this prevents the logo from shifting header content
// when the sidebar is opened
max-height: 100%;
max-width: 100%;
object-fit: contain; // contains logo without squishing/stretching
// allows some flexibility for wide logos
body:not(.has-sidebar-page) & {
max-width: unset;
@include viewport.until(sm) {
max-width: 25vw;
}
}
}
.d-header #site-text-logo {
font-size: clamp(var(--font-0), 2.5vw, var(--font-up-2));
.has-sidebar-page & {
white-space: wrap;
line-height: var(--line-height-medium);
@include line-clamp(2);
}
}
#main-outlet-wrapper {
padding: 0;
body.has-sidebar-page & {
.sidebar-wrapper {
width: var(--d-sidebar-width);
}
}
body.has-full-page-chat & {
gap: 0;
}
.sidebar-wrapper {
width: 100%; // safari has issues without this
}
#main-outlet {
margin: 0 auto;
max-width: var(--d-max-width);
width: 100%;
body.has-full-page-chat & {
max-width: unset;
}
}
}
.has-full-page-chat:not(.discourse-sidebar) .full-page-chat {
border: none;
}
#main-outlet > .regular {
max-width: var(--d-max-width);
margin: 0 auto;
body.has-sidebar-page & {
margin: 0 auto;
}
}
.d-header .title:not(.title--minimized) {
// allowing overflow here isn't always ideal
// but works well enough most of the time
overflow: visible;
}
.d-header {
> .wrap {
.contents {
display: grid;
grid-template-areas: "logo lspace extra-info rspace panel";
grid-template-columns:
minmax(auto, 1fr)
auto
minmax(0, calc(var(--d-max-width)))
auto
minmax(auto, 1fr);
.d-header-mode {
grid-area: extra-info;
white-space: nowrap;
@include viewport.until(md) {
display: none;
}
}
.d-header .title {
min-width: auto;
}
.has-sidebar-page & {
// at wide widths, when 1fr > 0
// we want the panel to be the same width as the sidebar
// this way we can get more accurate centering
grid-template-columns:
calc(var(--d-sidebar-width) - 11px) // 11px is wrap padding
1fr
minmax(0, calc(var(--d-max-width)))
1fr
minmax(0, calc(var(--d-sidebar-width) - 11px));
gap: 1em;
// at narrower widths, when 1fr = 0
// we can center without matching the sidebar's width
// which allows the title to take up the remaining width
@media screen and (width <= 1400px) {
grid-template-columns:
calc(var(--d-sidebar-width) - 11px)
1fr
minmax(0, calc(var(--d-max-width)))
1fr
auto;
}
@media screen and (width <= 1000px) {
gap: 0.5em;
}
.d-header-mode {
grid-area: extra-info;
}
}
}
}
.header-sidebar-toggle {
grid-area: logo;
}
.before-header-panel-outlet {
grid-area: extra-info;
}
.d-header-mode {
.bootstrap-mode {
display: none;
}
}
.home-logo-wrapper-outlet {
grid-area: logo;
margin-left: 3.7em; // 2.7em hamburger width + 1em for margin
margin-right: 0.725em;
display: flex;
overflow: visible;
.title {
flex: 1 1 auto;
}
}
.panel {
grid-area: panel;
}
}
.extra-info-wrapper {
grid-area: extra-info;
max-width: var(--d-max-width);
width: 100%;
box-sizing: border-box;
padding: 0;
}
.header-search--enabled .floating-search-input-wrapper {
grid-area: extra-info;
@include viewport.until(md) {
grid-area: rspace;
}
@include viewport.until(sm) {
display: none;
}
}
body.has-sidebar-page {
.wrap {
max-width: unset; // undoing core default
}
.d-header-mode,
.extra-info-wrapper {
padding: 0;
}
@media screen and (width >= calc($reply-area-max-width + ($sidebar-width * 2))) {
#reply-control.show-preview {
margin-left: auto;
margin-right: auto;
}
.sidebar-container {
height: auto;
}
}
@media screen and (width <= calc($reply-area-max-width + ($sidebar-width * 2))) and (width >= calc($reply-area-max-width + calc($sidebar-width / 2))) {
#reply-control.show-preview:not(.fullscreen) {
margin-left: $sidebar-width;
width: auto;
// overruling new core composer changes
max-width: $reply-area-max-width;
transform: none;
}
.sidebar-container {
height: auto;
}
}
// overruling new core composer changes
@media screen and (min-width: $reply-area-max-width) {
#reply-control.show-preview:not(.fullscreen) {
max-width: $reply-area-max-width;
transform: none;
}
}
}
body.sidebar-animate {
#main-outlet-wrapper {
transition: none;
}
.d-header-wrap .wrap {
transition: none;
}
}
.d-header-icons {
display: flex;
}
.rtl {
.d-header .title {
margin-right: 3.7em; // 2.7em hamburger width + 1em for margin
margin-left: 0.725em;
}
}
// provides some extra space for login buttons
@media screen and (width >= 1400px) {
.anon {
.d-header .panel {
grid-column-start: -4;
}
}
}
+65
View File
@@ -0,0 +1,65 @@
// Fixing bulk select (only needed for desktop)
.bulk-select-enabled {
.topic-list-header {
position: relative;
top: 0;
}
.topic-author-avatar-data {
display: none;
}
.bulk-select.topic-list-data {
grid-area: bulk-select;
margin-left: -0.5em;
@media screen and (width <= 576px) {
margin-top: 0;
label {
padding-block: 0.345em;
}
}
input {
transform: scale(1.5);
}
}
}
.topic-list-header {
tr {
border: none;
}
.topic-list-data {
padding: 0;
&:not(.default) {
display: none;
}
&.default {
.bulk-select,
span:not(.bulk-select-topics, .d-button-label) {
display: none;
}
}
}
// bulk select
.bulk-select-topics {
position: absolute;
right: 0;
background: var(--secondary);
border-radius: 0 0 0 var(--d-border-radius);
display: flex;
gap: 0.5rem;
margin: 0.5rem;
button {
white-space: nowrap;
margin: 0;
}
}
}
+17 -19
View File
@@ -1,13 +1,12 @@
@use "lib/viewport";
.d-header {
box-shadow: none;
background: var(--background-color);
@include breakpoint(extra-large, $rule: min-width) {
padding-bottom: 1em;
}
}
.has-full-page-chat .d-header {
background-color: transparent;
@include viewport.from(xl) {
padding-bottom: var(--main-grid-gap);
}
}
.user-menu .quick-access-panel,
@@ -44,15 +43,18 @@
.d-header-icons
.header-color-scheme-toggle
.-expanded
> .d-icon {
> .d-icon,
.discourse-no-touch .header-sidebar-toggle button:hover .d-icon {
color: var(--header_primary-medium);
}
.discourse-no-touch .interface-color-selector-content {
border: none;
border-radius: var(--d-border-radius);
.btn {
border: none;
&:hover {
box-shadow: none;
}
@@ -62,10 +64,6 @@
.drop-down-mode .d-header-icons .active .icon,
.drop-down-mode .d-header-icons .header-color-scheme-toggle .-expanded {
border-color: transparent;
}
.drop-down-mode .d-header-icons .active .icon,
.drop-down-mode .d-header-icons .header-color-scheme-toggle .-expanded {
background-color: transparent;
}
@@ -73,14 +71,6 @@
color: var(--accent-text-color);
}
.user-menu .quick-access-panel li,
.user-notifications-list li,
.user-menu .quick-access-panel li.do-not-disturb,
.menu-panel .panel-body-bottom .btn,
.menu-panel .panel-body-bottom .btn:hover {
// background-color: var(--d-content-background);
}
body.login-page,
body.signup-page,
body.invite-page,
@@ -90,3 +80,11 @@ body.activate-account-page {
background: var(--background-color);
}
}
.header-dropdown-toggle.chat-header-icon .icon .chat-channel-unread-indicator {
border-color: var(--background-color);
}
.d-header-icons .badge-notification {
border-color: var(--background-color);
}
+1 -1
View File
@@ -3,7 +3,7 @@
.notifications-button-footer .reason .text,
.pinned-button .reason .text,
.more-topics__browse-more,
//footer-message might cause issues, not sure what possible stuff can be in there, but the general idea is to hide it bcs having an ugly H3 (what?) CTA at the bottom is just ugly imo
// footer-message might cause issues, not sure what possible stuff can be in there, but the general idea is to hide it bcs having an ugly H3 (what?) CTA at the bottom is just ugly imo
.footer-message {
display: none;
}
+15
View File
@@ -0,0 +1,15 @@
body.static-login {
#main-outlet-wrapper {
grid-template-areas:
"sidebar blank"
"sidebar content"
"sidebar below-content";
grid-template-rows: auto 1fr auto;
}
.login-welcome {
border-radius: none;
border: none;
box-shadow: none;
}
}
+53 -34
View File
@@ -1,97 +1,106 @@
@use "lib/viewport";
:root {
--main-grid-gap: 2em;
--main-grid-gap: 0.5em;
}
html:not(:has(.has-full-page-chat)) {
background-color: var(--background-color);
@include viewport.until(sm) {
background-color: var(--d-content-background);
}
}
body {
-webkit-font-smoothing: antialiased;
@include viewport.until(sm) {
background-color: var(--d-content-background);
}
}
#main-outlet-wrapper {
gap: var(--main-grid-gap);
}
body.has-sidebar-page.has-full-page-chat #main-outlet-wrapper {
grid-column-gap: var(--main-grid-gap);
background-color: var(--background-color);
}
body.has-full-page-chat:not(.has-sidebar-page) {
.d-header {
background-color: var(--background-color);
}
#main-outlet-wrapper {
gap: var(--main-grid-gap);
@include breakpoint(medium) {
@include viewport.until(lg) {
gap: 0;
}
}
}
body.has-sidebar-page #main-outlet-wrapper {
grid-template-columns: var(--d-sidebar-width) minmax(0, 1fr) 0px;
grid-template-columns: var(--d-sidebar-width) minmax(0, 1fr) 0;
#main-outlet {
max-width: unset;
}
}
body:not(.has-sidebar-page) #main-outlet-wrapper {
@include breakpoint(medium, $rule: min-width) {
grid-template-columns: 0px minmax(0, 1fr) 0px;
@include viewport.from(lg) {
grid-template-columns: 0 minmax(0, 1fr) 0;
}
}
body:not(.has-full-page-chat) {
@include breakpoint(extra-large, $rule: min-width) {
body:not(.has-full-page-chat, .wizard) {
@include viewport.from(xl) {
background-color: var(--background-color);
}
#main-outlet-wrapper {
@include breakpoint(medium) {
@include viewport.until(lg) {
--main-grid-gap: 0;
}
@include breakpoint(tablet, $rule: min-width) {
@media screen and (width >= 768px) {
gap: var(--main-grid-gap);
}
#main-outlet {
width: 100%;
padding-bottom: var(--spacing-block-l);
max-width: unset;
//thanks to random container elements on the page, I can't do a direct child selector here because it targets all the randomness, so I see no other option than MANUALLY adding every possible element that can appear in the main outlet YAY
.list-controls,
.list-container,
#topic-title,
.container.posts,
#topic-footer-buttons,
.more-topics__container,
.welcome-banner,
.container .user-main,
.reviewable,
.admin-content,
.discourse-post-event-upcoming-events,
.container.groups-index,
.body-page,
.container.badges,
.topic-above-footer-buttons-outlet .presence-users,
.global-notice {
@include breakpoint(medium, $rule: min-width) {
padding-bottom: var(--spacing-block-l);
border-radius: var(--d-border-radius-large);
background-color: var(--d-content-background);
@include viewport.until(lg) {
border-radius: 0;
}
html.composer-open & {
padding-bottom: var(--composer-height);
}
> *:not(.experimental-screen, .activate-account) {
@include viewport.from(lg) {
box-sizing: border-box;
max-width: 1000px;
margin-inline: auto;
padding-inline: var(--spacing-inline-l);
}
}
border-radius: var(--d-border-radius-large);
@include breakpoint(medium) {
border-radius: 0px;
}
background-color: var(--d-content-background);
}
}
}
#list-area {
.show-more.has-topics {
@include breakpoint(medium, $rule: min-width) {
@include viewport.from(lg) {
width: auto;
right: 50%;
transform: translateX(50%);
@@ -103,6 +112,7 @@ body:not(.has-full-page-chat) {
}
}
}
.topic-list-body {
padding-top: var(--spacing-block-m);
}
@@ -117,3 +127,12 @@ aside.onebox {
padding: 1em;
background-color: var(--d-content-background);
}
.no-ember {
#main-outlet {
border-radius: var(--d-border-radius-large);
margin: 0 var(--main-grid-gap) var(--main-grid-gap) var(--main-grid-gap);
padding: 2em;
max-height: calc(100vh - 50px - 1em - var(--main-grid-gap));
}
}
+49 -8
View File
@@ -1,3 +1,5 @@
@use "lib/viewport";
.user-main .about.collapsed-info .details {
background: var(--d-content-background);
}
@@ -8,7 +10,7 @@
}
.powered-by-discourse {
z-index: 9999;
z-index: 400;
}
.boxed.white {
@@ -40,10 +42,6 @@
border-radius: 0;
}
.d-editor-button-bar {
padding: 3px;
}
.open .grippie {
background-color: var(--accent-color);
}
@@ -73,8 +71,11 @@ input[type="color"]:focus,
background-color: var(--background-color);
}
.fk-d-menu__trigger.topic-list-layout-trigger {
display: none;
@include viewport.until(sm) {
// pinned topic excerpts are hidden on small screens too
.fk-d-menu__trigger.topic-list-layout-trigger {
display: none;
}
}
.search-container .search-header,
@@ -86,7 +87,7 @@ input[type="color"]:focus,
.user-main .about .details {
padding: 1em 1em 0;
border-bottom: 0px;
border-bottom: 0;
border-radius: var(--d-border-radius);
background-color: var(--primary-50);
}
@@ -98,3 +99,43 @@ input[type="color"]:focus,
.discourse-reactions-list .reactions {
gap: 0.15em;
}
.group-details-container {
border-radius: var(--d-border-radius);
}
.period-chooser-header {
border-radius: 0;
}
// compatibility with the top contributors sidebar theme component
// https://meta.discourse.org/t/top-contributors-sidebar/215110
.list-container
#list-area
> .contents
> .topic-list:has(.discourse-top-contributors) {
grid-template-areas: "head head" "body sidebar";
grid-template-rows: auto 1fr;
@include viewport.until(lg) {
grid-template-areas: "head head" "body body";
}
tbody {
display: flex;
}
.discourse-top-contributors {
width: auto;
box-sizing: border-box;
@include viewport.until(lg) {
display: none;
}
.top-contributors-heading {
font-size: var(--font-up-2);
padding-bottom: 0.5em;
}
}
}
+74 -40
View File
@@ -1,72 +1,93 @@
//temp sepeate file to avoid merge hell… to be distributed later
@include breakpoint(medium) {
@use "lib/viewport";
// temp separate file to avoid merge hell… to be distributed later
@include viewport.until(lg) {
html,
.d-header {
background-color: var(--secondary);
background-color: var(--d-content-background);
}
}
#main-outlet-wrapper {
*[class*="navigation-"] & {
@include breakpoint(mobile-extra-large) {
@include viewport.until(sm) {
padding: 0;
}
}
}
#main-outlet {
@include breakpoint(mobile-extra-large) {
@include viewport.until(sm) {
padding-top: var(--spacing-block-sm);
}
.list-controls {
@include breakpoint(mobile-extra-large) {
@include viewport.until(sm) {
padding-inline: var(
--spacing-inline-m
) !important; //override will be fixed when the whole chat page shenanigans is resolved
) !important; // override will be fixed when the whole chat page shenanigans is resolved
padding-block: var(--spacing-block-s);
border-bottom: 1px solid var(--primary-200);
}
.navigation-container {
@include breakpoint(mobile-extra-large) {
@include viewport.until(sm) {
gap: var(--spacing-inline-s);
//dont know why we even hide this crucial navigation on mobile
.category-breadcrumb.hidden,
.category-breadcrumb {
display: flex !important;
column-gap: var(--spacing-inline-s);
column-gap: var(--spacing-inline-m);
row-gap: var(--spacing-block-xs);
flex-basis: 100%;
li {
margin-right: 0;
margin-left: calc(
(var(--spacing-block-s) - 2px) * -1
); // 2px is width of the outline
}
.select-kit-header-wrapper {
gap: 0.25em;
}
.select-kit-header {
padding-block: var(--spacing-block-s);
padding-inline: 0;
border: 0;
background: var(--d-content-background);
}
}
.btn-default {
border: 0;
margin-right: 0;
.d-icon {
font-size: var(--font-up-1);
}
}
.fk-d-button-tooltip {
margin-right: 0;
margin-left: var(
--spacing-inline-xs
); //pure visual correction for horitzontal alignment
); // pure visual correction for horizontal alignment
&:has(#create-topic) {
order: 1;
}
}
}
#navigation-bar,
.navigation-controls,
.category-breadcrumb {
@include breakpoint(mobile-extra-large) {
@include viewport.until(sm) {
margin-bottom: 0;
}
}
.navigation-controls {
@include breakpoint(mobile-extra-large) {
@include viewport.until(sm) {
gap: var(--spacing-inline-s);
}
}
@@ -74,42 +95,31 @@
}
.list-container {
@include breakpoint(mobile-extra-large) {
@include viewport.until(sm) {
padding-inline: 0 !important;
}
.topic-list-body {
@include breakpoint(mobile-extra-large) {
@include viewport.until(sm) {
border-top: 0;
padding-top: 0;
}
}
.topic-list-item {
@include breakpoint(mobile-extra-large) {
box-shadow: none;
border-radius: 0;
//to be moved to topic card segment for general use
// .navigation-category & {
// .badge-category__wrapper {
// display: none;
// }
// }
}
}
}
#topic-title {
@include breakpoint(mobile-extra-large) {
padding-inline: var(--spacing-inline-m) !important;
@include viewport.until(sm) {
padding-inline: var(--spacing-inline-s) !important;
.title-wrapper {
gap: var(--spacing-block-s);
}
.topic-category {
order: -1;
}
//make mixin of this
// make mixin of this
.badge-category__wrapper {
font-size: var(--font-down-2-rem);
border-radius: var(--d-border-radius);
@@ -131,6 +141,15 @@
oklch(from var(--category-badge-color) 100% calc(c * 0.9) h)
);
}
.discourse-tags {
gap: var(--spacing-inline-xs);
&__tag-separator {
display: none;
}
}
.discourse-tag {
font-size: var(--font-down-2-rem);
padding: var(--spacing-inline-xs) var(--spacing-inline-s);
@@ -141,14 +160,14 @@
}
}
}
.container.posts {
@include breakpoint(mobile-extra-large) {
@include viewport.until(sm) {
padding-inline: var(--spacing-inline-xs) !important;
.main-avatar .avatar {
width: 40px;
height: 40px;
border-radius: var(--d-border-radius);
}
.topic-body {
@@ -157,18 +176,22 @@
font-size: var(--font-0-rem);
}
}
.contents {
padding-top: var(--spacing-block-m);
}
}
.small-action {
&-desc {
padding: var(--spacing-block-xs) 0;
}
//for core eventually, better way imo
// for core eventually, better way imo
.topic-avatar {
padding-top: 0;
align-items: center;
.d-icon {
font-size: var(--font-up-1);
}
@@ -178,32 +201,43 @@
}
#topic-footer-buttons {
@include breakpoint(mobile-extra-large) {
@include viewport.until(sm) {
padding-inline: var(--spacing-inline-xs) !important;
}
}
}
//should be changed in core, should not be a primary btn
//changing this into straight buttons to match the progress one, which doesnt work well with rounded corners
// should be changed in core, should not be a primary btn
// changing this into straight buttons to match the progress one, which doesn't work well with rounded corners
#topic-progress-wrapper {
.progress-back-container {
margin-right: 0;
margin-bottom: var(--spacing-block-xs);
.btn-primary.progress-back {
border-radius: 0;
background: var(--secondary);
border: 1px solid var(--tertiary-low);
color: var(--accent-color);
padding: var(--spacing-inline-s) var(--spacing-inline-m);
.d-icon {
color: var(--accent-color);
}
}
}
.topic-admin-menu-trigger {
border-radius: 0;
background: var(--secondary);
border: 1px solid var(--tertiary-low);
}
}
.mobile-device #reply-control.show-preview .submit-panel {
background-color: var(--background-color);
}
.d-editor-preview-wrapper {
outline: 2px solid var(--background-color);
}
+36 -8
View File
@@ -1,37 +1,64 @@
@use "lib/viewport";
.list-controls {
position: sticky;
top: var(--header-offset);
background: var(--d-content-background);
z-index: 100;
padding: 1.5rem 0 1rem 0;
z-index: z("base");
padding: 1.5rem 0 0 0;
max-width: unset;
@include viewport.until(sm) {
padding-bottom: 1em;
}
.navigation-container {
position: relative;
gap: 1rem;
@include viewport.from(sm) {
&:after {
content: "";
position: absolute;
left: 0;
right: 0;
bottom: -1rem;
height: 1rem;
background: linear-gradient(
to bottom,
var(--d-content-background),
transparent
);
}
}
.category-breadcrumb {
order: 1;
}
}
.combo-box .combo-box-header {
// needs more specificy than just in the button file
// needs more specificity than just in the button file
background-color: var(--secondary);
border-radius: var(--d-border-radius-large);
border-radius: var(--d-border-radius);
border: 1px solid var(--primary-300);
// font-size: var(--font-up-1-rem);
&:hover {
border: 1px solid var(--accent-color);
}
&:focus-visible {
.discourse-no-touch & {
background: var(--secondary);
color: var(--accent-color);
box-shadow: 0px 0px 0px 3px var(--button-box-shadow);
box-shadow: 0 0 0 3px var(--button-box-shadow);
.d-icon {
color: var(--accent-color);
}
}
}
}
.select-kit.combo-box.category-drop.has-selection
.category-drop-header:hover {
border-color: transparent;
@@ -47,7 +74,8 @@
.nav-pills > li button:hover {
.discourse-no-touch & {
background: transparent;
color: var(--accent-color);
color: var(--d-nav-color--hover);
&::after {
content: "";
position: absolute;
@@ -55,7 +83,7 @@
bottom: 0;
right: 0;
height: var(--d-nav-underline-height);
background: var(--accent-color);
background: var(--d-nav-color--hover);
}
}
}
-82
View File
@@ -1,82 +0,0 @@
.custom-search-banner-wrap {
display: grid;
grid-template-rows: 0.33fr 0.33fr 0.33fr;
grid-template-columns: 1fr 1fr;
grid-column-gap: 1em;
grid-row-gap: 0.5em;
border-bottom: 1px solid var(--primary-300);
padding: 1.5em 0 2.5em;
margin-bottom: 0;
@media screen and (max-width: 768px) {
padding: 1em;
}
h1 {
grid-column: 1/2;
grid-row: 1/-1;
text-align: left;
align-self: center;
margin: 0;
font-weight: 400;
color: var(--search-banner-text-color);
@media screen and (max-width: 1028px) {
font-size: var(--font-up-4);
grid-column: 1/-1;
grid-row: 1;
text-align: center;
margin-bottom: 0.5em;
}
@media screen and (max-width: 768px) {
text-align: left;
grid-column: 1/2;
grid-row: 1/-1;
font-size: var(--font-up-3);
}
@media screen and (max-width: 600px) {
grid-column: 1/-1;
grid-row: 1;
text-align: center;
margin-bottom: 0.5em;
}
}
.search-menu {
grid-column: 2/3;
grid-row: 1/-1;
width: 100%;
align-self: center;
@media screen and (max-width: 1028px) {
grid-row: 2/-1;
grid-column: 1/-1;
}
@media screen and (max-width: 768px) {
grid-column: 2/-1;
grid-row: 1/-1;
}
@media screen and (max-width: 600px) {
grid-row: 2/-1;
grid-column: 1/-1;
}
}
p {
display: none;
}
.search-input {
background: var(--d-content-background);
border: 1px solid var(--search-color);
box-shadow: 0 4px 10px rgba(52, 6, 121, 15%);
}
.search-menu .search-input:focus-within,
.search-menu-container .search-input:focus-within {
border: 1px solid var(--search-color);
outline: 2px solid var(--search-color);
}
.search-menu .d-icon,
.search-menu .searching .d-icon {
color: var(--search-color);
}
.panel-body {
z-index: z("dropdown");
}
.results {
background: var(--d-content-background);
}
}
+71
View File
@@ -0,0 +1,71 @@
.navigation-controls {
.topic-drafts-menu-trigger,
.fk-d-button-tooltip {
display: none;
}
}
.has-ai-conversations-sidebar {
.sidebar-new-topic-button__wrapper {
display: none;
}
}
.sidebar-new-topic-button {
flex: 1 1 auto;
&__wrapper {
box-sizing: border-box;
display: flex;
.mobile-view & {
margin: 0 0 1rem;
}
&:has(.topic-drafts-menu-trigger) {
.sidebar-new-topic-button {
border-radius: var(--d-button-border-radius) 0 0
var(--d-button-border-radius);
border-right: 1px solid var(--primary-300);
}
}
.fk-d-button-tooltip {
flex: 1 1 auto;
}
.topic-drafts-menu-trigger {
flex: 0 1 auto;
margin: 0;
border-radius: 0 var(--d-button-border-radius)
var(--d-button-border-radius) 0;
}
.fk-d-button-tooltip:has(button[disabled]) {
+ .topic-drafts-menu-trigger {
display: none;
}
.fk-d-tooltip__trigger {
background: var(--accent-color);
border-radius: 0 var(--d-button-border-radius)
var(--d-button-border-radius) 0;
padding-right: 0.65em;
.d-icon {
color: var(--secondary);
}
}
}
}
}
li.sidebar-section-link-wrapper[data-list-item-name="New Topic"] {
display: none;
}
.has-full-page-chat {
.sidebar-new-topic-button__wrapper {
display: none;
}
}
+27 -7
View File
@@ -1,18 +1,24 @@
@use "lib/viewport";
.sidebar-wrapper,
.sidebar-hamburger-dropdown {
@include breakpoint(medium) {
@include viewport.until(lg) {
background: var(--secondary);
.sidebar-footer-wrapper {
background: var(--secondary);
.sidebar-footer-container::before {
display: none;
}
}
}
.has-full-page-chat &,
.has-full-page-chat & .sidebar-footer-wrapper {
background: transparent;
}
.sidebar-container {
border-right: none;
}
@@ -20,31 +26,38 @@
.sidebar-sections {
padding: 0;
}
.sidebar-section-link {
transition: none;
border-radius: var(--d-border-radius);
}
.dropdown-menu__item .sidebar-section-link {
border-radius: 0px;
border-radius: 0;
}
}
.sidebar-section-wrapper {
@include breakpoint(extra-large, $rule: min-width) {
@include viewport.from(xl) {
padding-block: 0.45em;
}
@include breakpoint(mobile-extra-large) {
@include viewport.until(sm) {
.hamburger-panel .revamped & {
margin-bottom: var(--spacing-block-m);
}
}
.sidebar-section-header {
font-size: var(--font-down-2);
}
.sidebar-section-content {
margin: 0;
display: flex;
flex-direction: column;
@include breakpoint(extra-large, $rule: min-width) {
@include viewport.from(xl) {
gap: var(--spacing-block-xs);
}
}
@@ -52,6 +65,7 @@
.sidebar-wrapper .sidebar-sections {
--scrollbarThumbBg: var(--d-selected);
padding: 0 1rem;
}
.sidebar-section-link-wrapper .sidebar-section-link:focus,
@@ -63,11 +77,17 @@
.sidebar-new-topic-button__wrapper {
margin: 0 var(--spacing-inline-m) var(--spacing-block-l);
.sidebar-new-topic-button .d-icon {
display: none;
}
}
.sidebar-wrapper .sidebar-sections {
padding: 0 1rem;
// put the draft menu above the slide-out hamburger on small desktop screens
@include viewport.until(md) {
html:not(.mobile-view) {
.topic-drafts-menu-content {
z-index: z("modal", "overlay");
}
}
}
+543 -264
View File
@@ -1,15 +1,4 @@
// 390x844 mobile/portrait (Figma iPhone 13 & 14)
// 744x1133 tablet/portrait (Figma iPad mini 8.3)
// 1280x832 desktop small (Figma MacBook Air)
:root {
--hot-color: oklch(63.79% 0.1823 34.77);
}
$extra-small: 435px;
$small: 576px;
$medium: 980px;
$extra-large: 1280px;
@use "lib/viewport";
.topic-list .topic-list-item-separator {
display: none;
@@ -17,6 +6,7 @@ $extra-large: 1280px;
.topic-list > .topic-list-body > .topic-list-item.last-visit {
border-bottom: 1px solid var(--primary-300);
&:hover {
border-color: var(--accent-color);
}
@@ -26,138 +16,108 @@ $extra-large: 1280px;
border: none;
display: flex;
flex-direction: column;
gap: 1em;
@include breakpoint(medium) {
gap: 1.25em;
@include viewport.until(lg) {
gap: 0.5em;
padding: 0 0.5em;
}
}
.bulk-select-enabled .topic-list-item {
grid-template-areas:
"bulk-select avatar author status status . activity"
". topic-title topic-title topic-title likes-replies likes-replies category";
.bulk-select {
grid-area: bulk-select;
@include viewport.until(sm) {
gap: 0;
padding: 0;
margin: 0;
align-self: center;
justify-self: center;
label {
margin: 0;
}
}
@media screen and (max-width: $medium) {
grid-template-columns: 44px min-content min-content auto min-content min-content min-content;
grid-template-rows: 22px minmax(22px, auto);
grid-template-areas:
"bulk-select avatar author status status . activity"
". topic-title topic-title topic-title . . likes-replies"
". topic-title topic-title topic-title . . category";
}
@media screen and (max-width: $small) {
grid-template-columns: 25px auto repeat(6, 1fr);
grid-template-rows: auto auto auto;
grid-template-areas:
"bulk-select category-status category-status . . . . activity"
"topic-title topic-title topic-title topic-title topic-title topic-title topic-title topic-title"
"avatar author . . . . . likes-replies";
}
}
body.user-messages-page .topic-list-item {
.topic-category-status-data {
display: none;
}
grid-template-areas:
"avatar author status status . . activity"
". topic-title topic-title topic-title likes-replies likes-replies likes-replies";
&.excerpt-expanded {
grid-template-columns: 44px repeat(6, 1fr) auto;
grid-template-rows: 22px auto auto 30px;
grid-template-areas:
"avatar author status status . . . activity"
"avatar topic-title topic-title topic-title topic-title . . ."
". excerpt excerpt excerpt excerpt excerpt . ."
". excerpt excerpt excerpt excerpt excerpt likes-replies likes-replies";
@media screen and (max-width: $extra-large) {
grid-template-areas:
"avatar author status status . . . activity"
"avatar topic-title topic-title topic-title topic-title . . ."
". excerpt excerpt excerpt excerpt excerpt . likes-replies"
". excerpt excerpt excerpt excerpt excerpt . likes-replies";
}
}
@media screen and (max-width: $small) {
grid-template-columns: 25px auto repeat(6, 1fr);
grid-template-rows: auto auto;
grid-template-areas:
"topic-title topic-title topic-title topic-title topic-title topic-title topic-title activity"
"avatar author . . . . . likes-replies";
.topic-excerpt {
display: none;
}
}
}
.topic-list-item {
.topic-list-body .topic-list-item {
position: relative;
background: var(--d-content-background);
box-shadow: 0 0 12px 1px var(--topic-card-shadow);
text-overflow: ellipsis;
padding: 0.75em 1rem;
border: 1px solid var(--primary-300);
display: grid;
grid-template-columns: 44px min-content min-content auto min-content min-content min-content;
grid-template-rows: 22px minmax(22px, auto);
grid-template-columns: min-content min-content auto min-content;
grid-template-areas:
"avatar author status status . . activity"
". topic-title topic-title topic-title likes-replies likes-replies category";
grid-column-gap: 12px;
grid-row-gap: 8px;
"creator title title status"
"creator category activity likes-replies";
grid-column-gap: 0.75rem;
grid-row-gap: 0.5rem;
border-radius: var(--d-border-radius);
&.excerpt-expanded {
grid-template-columns: 44px repeat(6, 1fr) auto;
grid-template-rows: 22px auto auto 30px;
cursor: pointer;
.bulk-select-enabled & {
grid-template-columns: min-content min-content min-content auto min-content;
grid-template-areas:
"avatar author status status . . . activity"
"avatar topic-title topic-title topic-title topic-title . . ."
". excerpt excerpt excerpt excerpt excerpt . ."
". excerpt excerpt excerpt excerpt excerpt likes-replies category";
@media screen and (max-width: $extra-large) {
grid-template-areas:
"avatar author status status . . . activity"
"avatar topic-title topic-title topic-title topic-title . . ."
". excerpt excerpt excerpt excerpt excerpt . likes-replies"
". excerpt excerpt excerpt excerpt excerpt . category";
"bulk-select creator title title status"
"bulk-select creator category activity likes-replies";
}
@include viewport.until(sm) {
grid-template-areas:
"category category category status"
"creator title title title"
"activity activity activity likes-replies";
row-gap: 0.75em;
border: none;
border-bottom: 1px solid var(--primary-200);
box-shadow: none;
border-radius: 0;
}
&:hover {
.discourse-no-touch & {
border-color: var(--accent-color);
background: var(--d-content-background);
}
@media screen and (max-width: $small) {
grid-template-columns: 25px auto repeat(6, 1fr);
grid-template-rows: auto auto auto;
grid-template-areas:
"category-status category-status category-status . . . . activity"
"topic-title topic-title topic-title topic-title topic-title topic-title topic-title topic-title"
"avatar author . . . . . likes-replies";
.topic-excerpt {
}
&.selected {
box-shadow:
0 0 0 2px var(--accent-color),
0 0 12px 1px var(--topic-card-shadow);
}
&.excerpt-expanded {
@include viewport.until(sm) {
.topic-excerpt,
.link-bottom-line {
display: none;
}
}
@include viewport.from(sm) {
grid-template-areas:
"creator title title status"
"creator category activity likes-replies "
"creator excerpt excerpt excerpt";
.bulk-select-enabled & {
grid-template-areas:
"bulk-select creator title title status"
"bulk-select creator category activity likes-replies "
" bulk-select creator excerpt excerpt excerpt";
}
}
// when there is enough space, excerpt can be next to likes-replies
@include viewport.from(lg) {
grid-template-areas:
"creator title title status"
"creator category activity ."
"creator excerpt excerpt likes-replies";
}
}
@media screen and (max-width: $medium) {
grid-template-columns: 44px min-content min-content auto min-content min-content min-content;
grid-template-rows: 22px minmax(22px, auto);
grid-template-areas:
"avatar author status status . . activity"
". topic-title topic-title topic-title . . likes-replies"
". topic-title topic-title topic-title . . category";
}
@media screen and (max-width: $small) {
grid-template-columns: 25px auto repeat(6, 1fr);
grid-template-rows: auto auto auto;
grid-template-areas:
"category-status category-status category-status . . . . activity"
"topic-title topic-title topic-title topic-title topic-title topic-title topic-title topic-title"
"avatar author . . . . . likes-replies";
}
@include breakpoint(medium) {
border: none;
border-bottom: 1px solid var(--primary-200);
.link-top-line {
grid-area: title;
font-weight: 500;
display: flex;
align-items: center;
.title {
padding: 0;
}
}
// display contents
@@ -165,7 +125,8 @@ body.user-messages-page .topic-list-item {
td.posters,
td.posts,
td.views,
td.activity {
td.activity,
td.topic-category-status-data {
display: contents;
}
@@ -173,103 +134,88 @@ body.user-messages-page .topic-list-item {
padding: 0;
}
// avatar & author
.topic-author-avatar-data {
grid-area: avatar;
margin: 0;
}
.topic-author-avatar img.avatar {
width: 44px;
height: 44px;
border-radius: var(--d-border-radius);
@media screen and (max-width: $small) {
width: 25px;
height: 25px;
}
}
td.topic-author-data {
grid-area: author;
display: flex;
gap: 0.5em;
align-items: center;
}
.topic-author-data .topic-author {
color: var(--primary-500);
}
// status
.topic-status-card {
display: flex;
flex-direction: row;
gap: 4px;
align-items: center;
padding: 0 6px;
font-size: var(--font-down-2);
font-weight: 600;
border-radius: var(--d-border-radius);
border: 1px solid var(--status-color);
color: var(--status-color);
height: min-content;
grid-area: status;
width: min-content;
@media screen and (max-width: $small) {
height: calc(100% - 2px);
}
svg {
font-size: var(--font-down-1);
color: var(--status-color);
}
}
.topic-status-card.--bookmark {
display: none;
}
.topic-status-card.--pinned,
.topic-status-card.--unpinned {
--status-color: var(--primary-500);
cursor: pointer;
background-color: transparent;
line-height: unset;
}
.topic-status-card.--hot {
--status-color: var(--hot-color);
}
// title
td.main-link .link-top-line {
font-size: var(--font-0);
grid-area: topic-title;
font-weight: 500;
}
.link-top-line .event-date {
font-size: var(--font-down-3);
}
td.main-link a.topic-status {
// display:nones
td.main-link a.topic-status,
.link-bottom-line,
.badge-notification.new-topic::before {
display: none;
}
td.main-link .link-top-line a.raw-topic-link {
padding: 0;
.topic-category-data {
grid-area: category;
display: flex;
}
.topic-post-badges .badge-notification.unread-posts {
background-color: var(--tertiary);
color: var(--tertiary);
overflow: hidden;
height: 8px;
width: 8px;
padding: 0;
top: -2px;
min-width: unset;
.badge-category__wrapper {
border-radius: var(--d-border-radius);
padding: 0.25em 0.5rem;
background-color: light-dark(
oklch(from var(--category-badge-color) 97% calc(c * 0.3) h),
oklch(from var(--category-badge-color) 45% calc(c * 0.5) h)
);
@include viewport.until(md) {
padding: 0.25em 0.5rem;
font-size: var(--font-down-2);
}
.badge-category__name {
color: light-dark(
oklch(from var(--category-badge-color) 20% calc(c * 1) h),
oklch(from var(--category-badge-color) 100% calc(c * 0.9) h)
);
}
}
// excerpt
.topic-excerpt {
grid-area: excerpt;
margin: 0;
font-size: var(--font-down-2);
// OP avatar
.topic-creator-data {
grid-area: creator;
.avatar {
height: 50px;
width: 50px;
border-radius: var(--d-border-radius);
@include viewport.until(sm) {
height: 30px;
width: 30px;
border-radius: 0.25rem;
}
}
}
.dot-separator {
width: 0.25em;
height: 0.25em;
background-color: var(--primary-500);
border-radius: 100%;
margin-inline: 0.25em;
}
// topic activity, icon, text
.topic-activity-data {
@include ellipsis;
grid-area: activity;
}
.topic-activity {
display: flex;
font-size: var(--font-down-1);
height: 100%;
align-items: center;
gap: 0.25em;
}
.topic-activity__type {
border-radius: 0.25rem;
display: flex;
align-items: center;
justify-content: center;
}
.topic-activity__username {
@include ellipsis;
margin-left: 0.25em;
}
// timestamp
@@ -281,46 +227,87 @@ body.user-messages-page .topic-list-item {
padding: 0;
}
// metadata
// metadata - category
td.main-link .link-bottom-line {
display: none;
// status
.topic-status-data {
grid-area: status;
}
td.topic-category-status-data {
display: contents;
@media screen and (max-width: $small) {
grid-area: category-status;
display: flex;
gap: 0.5em;
align-items: center;
}
}
td.topic-category-status-data .badge-category__wrapper {
grid-area: category;
}
td.topic-category-status-data .badge-category__wrapper {
overflow: unset;
.topic-status-card {
height: min-content;
margin-left: auto;
display: flex;
flex-direction: row;
gap: 0.25em;
align-items: center;
padding: 0.2em 0.5rem;
font-size: var(--font-down-3);
font-weight: 600;
border-radius: var(--d-border-radius);
padding: 6px;
align-self: flex-end;
background-color: light-dark(
oklch(from var(--category-badge-color) 97% calc(c * 0.3) h),
oklch(from var(--category-badge-color) 45% calc(c * 0.5) h)
);
border: 1px solid var(--status-color);
color: var(--status-color);
width: min-content;
@media screen and (max-width: $small) {
padding: 2px 6px;
&.--pinned {
--status-color: var(--primary-500);
}
.badge-category__name {
color: light-dark(
oklch(from var(--category-badge-color) 20% calc(c * 1) h),
oklch(from var(--category-badge-color) 100% calc(c * 0.9) h)
);
&.--hot {
--status-color: #e45735;
}
@include viewport.from(lg) {
position: absolute;
right: 1rem;
top: 0;
transform: translateY(-45%);
background-color: var(--d-content-background);
}
svg {
font-size: var(--font-down-1);
color: var(--status-color);
}
}
.link-top-line .event-date {
margin-left: 0.5em;
font-size: var(--font-down-3);
}
.topic-list-data {
padding: 0;
}
.topic-post-badges .badge-notification.unread-posts,
.topic-post-badges .badge-notification.new-topic {
background-color: var(--tertiary);
color: var(--tertiary);
overflow: hidden;
height: 8px;
width: 8px;
padding: 0;
top: -2px;
min-width: unset;
}
// metadata - excerpt
.topic-excerpt {
grid-area: excerpt;
margin: 0;
padding: 0;
font-size: var(--font-down-2);
width: 100%;
.excerpt__contents {
color: var(--primary-high);
}
// default category position hidden
.badge-category__wrapper {
display: none;
}
}
td.main-link .discourse-tags {
display: none;
}
@@ -339,9 +326,9 @@ body.user-messages-page .topic-list-item {
gap: 0.5em;
justify-content: flex-end;
height: min-content;
align-self: flex-end;
padding-bottom: 4px;
align-self: center;
}
.topic-likes-replies-data .topic-likes,
.topic-likes-replies-data .topic-replies {
display: flex;
@@ -349,27 +336,319 @@ body.user-messages-page .topic-list-item {
gap: 0.5em;
align-items: center;
color: var(--primary-500);
font-size: var(--font-down-1-rem);
svg {
color: var(--primary-600);
}
}
}
.topic-list-header {
display: none;
}
.bulk-select {
grid-area: bulk-select;
padding: 0;
margin: 0;
align-self: center;
justify-self: center;
.topic-list-item {
background: var(--d-content-background);
box-shadow: 0px 0px 12px 1px var(--topic-card-shadow);
&:hover {
.discourse-no-touch & {
border-color: var(--accent-color);
background: var(--d-content-background);
@include viewport.until(sm) {
align-self: flex-start;
}
label {
margin: 0;
}
&th {
display: none;
}
}
&.selected {
box-shadow: 0px 0px 0px 2px var(--accent-color),
0px 0px 12px 1px var(--topic-card-shadow);
}
// Bookmarks
.topic-list-item.bookmark-list-item {
.link-bottom-line {
font-size: unset;
}
// regular card without excerpt class
grid-template-columns: 20px min-content min-content auto min-content min-content min-content;
grid-template-areas:
". . . . . . dropdown"
"avatar update metadata metadata metadata . category";
@include viewport.until(sm) {
grid-template-columns: min-content min-content auto min-content min-content min-content min-content;
grid-template-areas:
" . . . . . . dropdown"
"update metadata metadata metadata metadata category category";
.avatar {
display: none;
}
}
&.has-metadata {
grid-template-columns: 20px min-content min-content auto min-content min-content min-content;
@include viewport.until(sm) {
grid-template-areas:
". . . . . . . dropdown"
"update update metadata metadata metadata metadata category category";
.avatar {
display: none;
}
}
}
// card with excerpt (all in horizon since the toggle is gone)
&.excerpt-expanded {
grid-template-columns: 20px min-content auto minmax(0, 100px);
grid-template-areas:
". . . dropdown"
"avatar update metadata metadata"
"excerpt excerpt excerpt ."
"excerpt excerpt excerpt category";
@include viewport.from(xl) {
grid-template-columns: 20px min-content auto min-content;
}
@include viewport.until(sm) {
grid-template-columns: auto min-content;
grid-template-areas:
". dropdown"
"category category";
.post-excerpt,
.avatar {
display: none;
}
}
&.has-metadata {
grid-template-columns: 20px min-content auto min-content;
grid-template-areas:
". . . dropdown"
"avatar update metadata metadata"
"excerpt excerpt excerpt . "
"excerpt excerpt excerpt category";
@include viewport.until(sm) {
grid-template-columns: auto min-content;
grid-template-areas:
" . dropdown"
"metadata category";
.bookmark-metadata {
flex-wrap: wrap;
}
}
}
.badge-category__wrapper {
align-self: flex-end;
height: min-content;
max-width: 100%;
}
}
td.author-avatar {
grid-area: avatar;
}
td.main-link .link-bottom-line {
display: contents;
.badge-category__wrapper {
grid-area: category;
display: flex;
align-items: center;
width: min-content;
justify-self: flex-end;
}
}
td.main-link .link-top-line {
display: contents;
.bookmark-metadata {
grid-area: metadata;
margin: 0;
display: flex;
align-items: center;
gap: var(--spacing-inline-xs);
}
.bookmark-metadata-item {
margin: 0;
vertical-align: middle;
}
.bookmark-status-with-link {
grid-column: 1/-2;
grid-row: 1/2;
}
}
.post-excerpt {
grid-area: excerpt;
margin: 0;
}
.topic-list-data:last-of-type {
display: contents;
.bookmark-actions-dropdown {
grid-area: dropdown;
align-self: flex-start;
height: 1em;
.select-kit-header {
padding-top: 0;
margin-left: auto;
align-items: center;
background: transparent;
}
.select-kit-header-wrapper {
height: 1em;
width: 1em;
}
}
}
.post-metadata.topic-list-data.updated-at {
grid-area: update;
}
td.activity .post-activity {
display: none;
}
}
// Assigned List
.topic-list-item.assigned-list-item {
.topic-status-card {
display: none;
position: relative;
top: unset;
right: unset;
}
td.main-link .link-top-line {
grid-column: 1/-3;
}
grid-template-columns: 20px min-content min-content auto min-content min-content min-content;
grid-template-areas:
". . . . . status dropdown"
"activity . . . . likes-replies category";
@include viewport.until(sm) {
grid-template-columns: 20px min-content min-content auto min-content min-content min-content 36px;
grid-template-areas:
"category category . . . . status dropdown"
". . . . . . . . "
"activity . . . . . . likes-replies";
}
.assign-topic-buttons {
display: contents;
.assign-actions-dropdown {
grid-area: dropdown;
justify-content: flex-end;
height: 1em;
.select-kit-header {
padding-top: 0;
margin-left: auto;
align-items: center;
background: transparent;
}
.select-kit-header-wrapper {
height: 1em;
width: 1em;
}
}
}
td.topic-category-status-data {
display: contents;
}
}
// User Messages
body.user-messages-page {
.topic-list-body {
gap: 0;
}
.topic-list .topic-list-data.posters a:not(.latest) {
display: block;
}
.topic-list-item {
border-radius: 0;
box-shadow: none;
border-bottom: 1px solid var(--primary-200);
border-top: none;
border-right: none;
border-left: none;
display: grid;
grid-template-areas: "title activity" "posters .";
grid-template-columns: auto auto;
grid-template-rows: auto auto;
&:hover {
.discourse-no-touch & {
background-color: var(--primary-low);
border-color: var(--primary-200);
}
}
td.topic-category-data,
td.topic-likes-replies-data,
td.topic-status-data,
td.topic-creator-data {
display: none;
}
.main-link .link-top-line {
grid-area: title;
}
&.visited .main-link .link-top-line {
font-weight: normal;
}
td.topic-activity-data {
grid-area: activity;
}
td.topic-list-data.posters {
grid-area: posters;
display: flex;
align-items: center;
height: 100%;
a {
margin-right: 4px;
}
.avatar {
width: 20px;
height: 20px;
border-radius: 4px;
background-color: var(--primary-low);
}
}
}
}
.event-date-container {
display: inline-flex;
position: relative;
top: -0.25em; // optical alignment
}
+54 -40
View File
@@ -1,3 +1,5 @@
@use "lib/viewport";
.post-stream {
.contents {
font-size: var(--font-up-1);
@@ -6,58 +8,66 @@
}
}
.container.posts .topic-navigation {
// super fragile because new sticky topic title doesnt have a calculated value (= 53px with this font and size but…)
top: calc(
var(--header-offset, 60px) + 53px + calc(var(--spacing-block-l) * 2)
);
z-index: 300;
}
.timeline-container .topic-timeline {
min-width: unset; // why we have this?
.timeline-scrollarea {
border-left: 1px solid var(--accent-color);
}
.timeline-scroller {
padding: 0.25em;
border: 1px solid var(--accent-color);
border-radius: 0.75em;
padding-left: 0.5em;
margin-left: calc(-0.5em - 2.5px);
background: var(--d-content-background);
height: 40px !important; // height is coming from element style have no other choice
}
.timelime-scroller-content {
display: flex;
flex-direction: column;
gap: 0.25em;
}
.timeline-replies,
.timeline-ago {
line-height: 1;
}
.timeline-ago {
// font-size: var(--font-down-1);
}
.timeline-handle {
background-color: var(--accent-color);
width: 3px;
border-radius: 2px;
height: calc(100% - 6px);
.timeline-scroller {
@include viewport.from(lg) {
margin-left: -4.5px;
background: var(--d-content-background);
height: 40px !important; // height is coming from element style have no other choice
}
.timeline-replies,
.timeline-ago {
line-height: 1;
}
}
.timeline-handle {
background-color: var(--accent-color);
@include viewport.from(lg) {
width: 8px;
border-radius: 10px;
height: calc(100% - 6px);
}
}
}
}
.container.posts,
#topic-footer-buttons {
padding: 0 24px;
// should probably get rid of this extra specificity class in core?
.timeline-container.timeline-fullscreen {
@include viewport.until(lg) {
.topic-timeline
.timeline-scrollarea
.timeline-scroller
.timeline-scroller-content {
padding-right: 0.5em;
}
}
}
.container.posts {
grid-template-columns: auto 150px;
@media screen and (max-width: 924px) {
grid-template-columns: auto 8em;
@media screen and (width <= 924px) {
grid-template-columns: auto auto;
}
.post-notice {
padding: var(--spacing-block-sm);
border-radius: var(--d-border-radius);
font-size: var(--font-down-1-rem);
.d-icon {
font-size: var(--font-up-1);
width: 1em;
}
}
}
.timeline-container .topic-timeline .timeline-ago {
@@ -101,3 +111,7 @@
nav.post-controls .actions button {
font-size: var(--font-0);
}
.archetype-private_message {
--pm-border-radius: var(--d-border-radius);
}
+2 -2
View File
@@ -3,8 +3,8 @@
--d-border-radius-large: 20px;
--d-border-radius: 8px;
--d-input-border-radius: 6px;
// --d-sidebar-row-height: 2.8em;
//the idea is: block spacing can grow with font-size, but inline spacing should not to maintain horizontal (text) alignment
// the idea is: block spacing can grow with font-size, but inline spacing should not to maintain horizontal (text) alignment
--spacing-block-xs: 0.25em;
--spacing-block-s: 0.5em;
--spacing-block-sm: 0.75em;
+117
View File
@@ -0,0 +1,117 @@
@use "lib/viewport";
.welcome-banner {
&__wrap {
display: grid;
grid-template-rows: 0.33fr 0.33fr 0.33fr;
grid-template-columns: 1fr 1fr;
grid-column-gap: 1em;
grid-row-gap: 0.5em;
border-bottom: 1px solid var(--primary-300);
padding: 1.5em 0 2.5em;
margin-bottom: 0;
@media screen and (width <= 768px) {
padding: 1em;
}
@include viewport.until(sm) {
display: block;
padding: 0.5em;
margin-top: 0;
}
.search-menu {
grid-column: 2/3;
grid-row: 1/-1;
width: 100%;
align-self: center;
@media screen and (width <= 1028px) {
grid-row: 2/-1;
grid-column: 1/-1;
}
@media screen and (width <= 768px) {
grid-column: 2/-1;
grid-row: 1/-1;
}
@media screen and (width <= 600px) {
grid-row: 2/-1;
grid-column: 1/-1;
}
@include viewport.until(sm) {
display: none;
}
}
p {
display: none;
}
}
.search-menu .search-input,
.search-menu-container .search-input {
background: var(--d-content-background);
border: 1px solid var(--search-color);
box-shadow: 0 4px 10px rgb(52, 6, 121, 15%);
}
.search-menu .search-input:focus-within,
.search-menu-container .search-input:focus-within {
border: 1px solid var(--search-color);
outline: 2px solid var(--search-color);
}
.search-menu .d-icon,
.search-menu .searching .d-icon,
.search-menu .searching .show-advanced-search .d-icon {
color: var(--search-color);
}
.panel-body {
z-index: z("dropdown");
}
.results {
background: var(--d-content-background);
}
&__title {
grid-column: 1/2;
grid-row: 1/-1;
text-align: left;
align-self: center;
margin: 0;
font-weight: 400;
color: var(--search-color);
@media screen and (width <= 1028px) {
font-size: var(--font-up-4);
grid-column: 1/-1;
grid-row: 1;
text-align: center;
margin-bottom: 0.5em;
}
@media screen and (width <= 768px) {
text-align: left;
grid-column: 1/2;
grid-row: 1/-1;
font-size: var(--font-up-3);
}
@media screen and (width <= 600px) {
grid-column: 1/-1;
grid-row: 1;
text-align: center;
margin-bottom: 0.5em;
}
@include viewport.until(sm) {
font-size: var(--font-up-2);
}
}
}
+11
View File
@@ -0,0 +1,11 @@
enable_welcome_banner:
default: true
description: "Overrides the core `enable welcome banner` site setting"
search_experience:
type: enum
default: search_field
choices:
- search_field
- search_icon
description: "Overrides the core `search experience` site setting"
+54
View File
@@ -0,0 +1,54 @@
# frozen_string_literal: true
describe "Composer peek", type: :system do
fab!(:current_user) { Fabricate(:user, refresh_auto_groups: true) }
fab!(:topic) { Fabricate(:topic_with_op) }
let(:topic_page) { PageObjects::Pages::Topic.new }
let(:composer) { PageObjects::Components::Composer.new }
before do
upload_theme
sign_in(current_user)
end
it "does not show composer peek for small windows" do
topic_page.visit_topic(topic)
topic_page.click_footer_reply
expect(composer).to be_opened
resize_window(width: 600) { expect(page).to have_no_css(".peek-mode-toggle") }
end
it "turns on composer peek and remembers this preference on page load" do
topic_page.visit_topic(topic)
topic_page.click_footer_reply
expect(composer).to be_opened
resize_window(width: 1380) do
find(".peek-mode-toggle").click
expect(page).to have_css("body.peek-mode-active")
topic_page.visit_topic(topic)
topic_page.click_footer_reply
expect(composer).to be_opened
expect(page).to have_css("body.peek-mode-active")
find(".peek-mode-toggle").click
expect(page).to have_no_css("body.peek-mode-active")
end
end
it "hides the composer preview when toggling" do
topic_page.visit_topic(topic)
topic_page.click_footer_reply
expect(composer).to be_opened
expect(composer).to have_composer_preview
resize_window(width: 1380) do
find(".peek-mode-toggle").click
expect(page).to have_css("body.peek-mode-active")
expect(composer).to have_no_composer_preview
end
end
end
+22
View File
@@ -0,0 +1,22 @@
# frozen_string_literal: true
RSpec.describe "Core features", type: :system do
fab!(:current_user) { Fabricate(:user, refresh_auto_groups: true) }
let(:composer) { PageObjects::Components::Composer.new }
before { upload_theme_or_component }
it_behaves_like "having working core features",
skip_examples: %i[search:quick_search topics:create]
it "creates a new topic" do
sign_in(current_user)
visit("/new-topic")
composer.fill_title("This is a new topic")
composer.fill_content("This is a long enough sentence.")
expect(page).to have_css(".d-editor-preview p", visible: true)
within(".save-or-cancel") { click_button("Create Topic") }
expect(page).to have_content("This is a new topic")
expect(page).to have_content("This is a long enough sentence.")
end
end
+26 -14
View File
@@ -1,7 +1,16 @@
# frozen_string_literal: true
require_relative "./page_objects/components/user_color_palette_selector"
describe "Horizon theme | High level", type: :system do
let!(:theme) { upload_theme }
let!(:theme) do
horizon_theme = upload_theme
ColorScheme
.where(theme_id: horizon_theme.id)
.where.not("name LIKE '%Dark%'")
.update_all(user_selectable: true)
horizon_theme
end
fab!(:current_user) { Fabricate(:user) }
fab!(:tag_1) { Fabricate(:tag, name: "wow-cool") }
fab!(:tag_2) { Fabricate(:tag, name: "another-tag") }
@@ -10,6 +19,7 @@ describe "Horizon theme | High level", type: :system do
let(:topic_list) { PageObjects::Components::TopicList.new }
let(:topic_page) { PageObjects::Pages::Topic.new }
let(:sidebar) { PageObjects::Components::NavigationMenu::Sidebar.new }
let(:palette_selector) { PageObjects::Components::UserColorPaletteSelector.new }
def run_all_high_level_tests
expect(page).to have_css(".experimental-screen")
@@ -25,27 +35,29 @@ describe "Horizon theme | High level", type: :system do
topic_item = find(topic_list.topic_list_item_class(topic_1))
expect(topic_item.all("td").map { |el| el["class"] }).to eq(
[
"main-link clearfix topic-list-data",
"activity num topic-list-data age",
"topic-author-data",
"topic-category-status-data",
"topic-author-avatar-data",
"main-link topic-list-data",
"topic-status-data",
"topic-category-data",
"topic-likes-replies-data",
"topic-creator-data",
"topic-activity-data",
],
)
# Can see a topic in the list and navigate to it successfully
# Can see a topic in the list and navigate to it successfully.
topic_list.visit_topic(topic_1)
expect(topic_page).to have_topic_title(topic_1.title)
# Can change site colors from the sidebar palette, which are remembered across page reloads
palette_menu =
PageObjects::Components::DMenu.new(find(".sidebar-footer-actions .user-color-palette"))
palette_menu.expand
find(".color-palette-menu__content .color-palette-menu__item[data-color='marigold']").click
expect(page).to have_css(".custom-color-marigold")
# Can change site colors from the sidebar palette, which are remembered
# across page reloads.
marigold_palette = ColorScheme.find_by(name: "Marigold")
palette_selector.open_palette_menu
palette_selector.click_palette_menu_item(marigold_palette.name)
expect(palette_selector).to have_no_palette_menu
page.refresh
expect(page).to have_css(".custom-color-marigold")
expect(palette_selector).to have_selected_palette(marigold_palette)
expect(palette_selector).to have_tertiary_color(marigold_palette)
end
it "works for anon" do
@@ -0,0 +1,53 @@
# frozen_string_literal: true
module PageObjects
module Components
class UserColorPaletteSelector < PageObjects::Components::Base
def sidebar_footer_button_css
".sidebar-footer-actions .user-color-palette-selector"
end
def palette_menu
PageObjects::Components::DMenu.new(find(sidebar_footer_button_css))
end
def open_palette_menu
palette_menu.expand
end
def has_no_palette_menu?
has_no_css?(".user-color-palette-selector-content")
end
def click_palette_menu_item(palette_name)
find(
".user-color-palette-menu__content .user-color-palette-menu__item[data-color-palette='#{palette_name}']",
).click
end
def has_selected_palette?(palette)
has_css?(".user-color-palette-selector[data-selected-color-palette-id='#{palette.id}']")
end
def has_loaded_css?
has_css?(".user-color-palette-selector.user-color-palette-css-loaded")
end
def has_tertiary_color?(palette)
computed_color_hex =
page.evaluate_script(
"getComputedStyle(document.documentElement).getPropertyValue('--tertiary')",
)
computed_color_hex == "#" + palette.colors.find { |color| color.name == "tertiary" }.hex
end
def has_computed_color?(color)
computed_background_color =
page.evaluate_script(
"getComputedStyle(document.querySelector(\"li.sidebar-section-link-wrapper[data-list-item-name='everything'] .active\")).backgroundColor",
)
computed_background_color == color
end
end
end
end
+55
View File
@@ -0,0 +1,55 @@
# frozen_string_literal: true
RSpec.describe "Sidebar New Topic Button", system: true do
before { upload_theme }
fab!(:group)
fab!(:user) { Fabricate(:user, trust_level: 3, groups: [group]) }
fab!(:category)
fab!(:private_category) do
c = Fabricate(:category_with_definition)
c.set_permissions(group => :readonly)
c.save
c
end
context "for signed in users" do
before { sign_in(user) }
it "renders the new topic button in the sidebar" do
visit("/latest")
expect(page).to have_css(".sidebar-new-topic-button__wrapper")
expect(page).to have_css(".sidebar-new-topic-button:not(.disabled)")
end
it "opens the composer when clicked" do
visit("/")
find(".sidebar-new-topic-button").click
expect(page).to have_css("#reply-title")
end
it "shows draft menu when drafts exist" do
Draft.create!(user: user, draft_key: "topic_1", data: {})
visit("/")
expect(page).to have_css(".sidebar-new-topic-button__wrapper .topic-drafts-menu-trigger")
end
it "disables button when visiting read-only category" do
visit("/c/#{private_category.slug}/#{private_category.id}")
expect(page).to have_css(".sidebar-new-topic-button[disabled]")
visit("/c/#{category.slug}/#{category.id}")
expect(page).not_to have_css(".sidebar-new-topic-button[disabled]")
end
end
context "for anon" do
it "does not render the sidebar button for anons" do
visit("/latest")
expect(page).not_to have_css(".sidebar-new-topic-button__wrapper")
expect(page).not_to have_css(".sidebar-new-topic-button:not(.disabled)")
end
end
end
@@ -0,0 +1,119 @@
# frozen_string_literal: true
require_relative "./page_objects/components/user_color_palette_selector"
describe "Horizon theme | User color palette selector", type: :system do
let(:set_theme_as_default) { true }
let!(:theme) do
horizon_theme = upload_theme(set_theme_as_default: set_theme_as_default)
ColorScheme.where(theme_id: horizon_theme.id).update_all(user_selectable: true)
horizon_theme
end
fab!(:current_user) { Fabricate(:user) }
let(:sidebar) { PageObjects::Components::NavigationMenu::Sidebar.new }
let(:palette_selector) { PageObjects::Components::UserColorPaletteSelector.new }
let(:interface_color_mode) { PageObjects::Components::InterfaceColorMode.new }
let(:interface_color_selector) do
PageObjects::Components::InterfaceColorSelector.new(".sidebar-footer-actions")
end
let(:marigold_palette) { ColorScheme.find_by(name: "Marigold") }
let(:marigold_palette_dark) { ColorScheme.find_by(name: "Marigold Dark") }
before { SiteSetting.interface_color_selector = "sidebar_footer" }
it "does not show the sidebar button if there are no user-selectable color palettes" do
ColorScheme.update_all(user_selectable: false)
visit "/"
expect(page).to have_no_css(palette_selector.sidebar_footer_button_css)
end
describe "for logged in user" do
before { sign_in(current_user) }
it "can open the user color palette menu and select a palette, which is preseved on reload" do
visit "/"
palette_selector.open_palette_menu
palette_selector.click_palette_menu_item(marigold_palette.name)
expect(palette_selector).to have_no_palette_menu
expect(palette_selector).to have_selected_palette(marigold_palette)
expect(palette_selector).to have_loaded_css
expect(palette_selector).to have_tertiary_color(marigold_palette)
page.refresh
expect(palette_selector).to have_selected_palette(marigold_palette)
end
it "uses the dark version of the palette if the user selects dark mode" do
visit "/"
palette_selector.open_palette_menu
palette_selector.click_palette_menu_item(marigold_palette.name)
expect(palette_selector).to have_no_palette_menu
expect(palette_selector).to have_selected_palette(marigold_palette)
expect(palette_selector).to have_loaded_css
expect(palette_selector).to have_computed_color("oklch(0.92 0.0708528 68.5036)")
interface_color_selector.expand
interface_color_selector.dark_option.click
expect(interface_color_mode).to have_dark_mode_forced
expect(palette_selector).to have_computed_color("oklch(0.481966 0.0354264 68.5036)")
page.refresh
expect(palette_selector).to have_selected_palette(marigold_palette)
expect(palette_selector).to have_computed_color("oklch(0.481966 0.0354264 68.5036)")
end
context "when the theme is not default but is selected by a user" do
let(:set_theme_as_default) { false }
it "can open the user color palette menu and select a palette, which is preseved on reload" do
theme.update!(user_selectable: true)
current_user.user_option.update!(theme_ids: [theme.id])
visit "/"
palette_selector.open_palette_menu
palette_selector.click_palette_menu_item(marigold_palette.name)
expect(palette_selector).to have_no_palette_menu
expect(palette_selector).to have_selected_palette(marigold_palette)
expect(palette_selector).to have_loaded_css
expect(palette_selector).to have_tertiary_color(marigold_palette)
end
end
end
describe "for anon" do
it "can open the user color palette menu and select a palette, which is preseved on reload" do
visit "/"
palette_selector.open_palette_menu
palette_selector.click_palette_menu_item(marigold_palette.name)
expect(palette_selector).to have_no_palette_menu
expect(palette_selector).to have_selected_palette(marigold_palette)
expect(palette_selector).to have_loaded_css
expect(palette_selector).to have_tertiary_color(marigold_palette)
end
it "uses the dark version of the palette if the user selects dark mode, which is preserved on reload" do
visit "/"
palette_selector.open_palette_menu
palette_selector.click_palette_menu_item(marigold_palette.name)
expect(palette_selector).to have_no_palette_menu
expect(palette_selector).to have_selected_palette(marigold_palette)
expect(palette_selector).to have_loaded_css
expect(palette_selector).to have_computed_color("oklch(0.92 0.0708528 68.5036)")
interface_color_selector.expand
interface_color_selector.dark_option.click
expect(interface_color_mode).to have_dark_mode_forced
expect(palette_selector).to have_selected_palette(marigold_palette)
expect(palette_selector).to have_loaded_css
expect(palette_selector).to have_computed_color("oklch(0.481966 0.0354264 68.5036)")
page.refresh
expect(palette_selector).to have_selected_palette(marigold_palette)
expect(palette_selector).to have_computed_color("oklch(0.481966 0.0354264 68.5036)")
end
end
end
+3
View File
@@ -0,0 +1,3 @@
export default {
extends: ["@discourse/lint-configs/stylelint"],
};