weird icon indicating copy to clipboard operation
weird copied to clipboard

Theming: New Theming Pattern for Easier Customization

Open hnb-ku opened this issue 1 year ago • 10 comments

This issue proposes a new pattern to make theming the application easier and more maintainable.

Core Idea:

The idea is to shift towards a more component-centric architecture, separating data fetching and logic from presentation, and allowing themes to override both CSS and component templates (with guardrails).

Implementation Details:

  1. Minimal Logic in Routes: Remove styling and logic from +page.svelte files. Keep most non-client-side logic in +page.server.ts and pass data down to components.
  2. Component-Based Routes: Add a components folder inside each route, containing smaller components focused on presentation.
  3. Common Component Library: Move frequently used components to $lib/components for global reusability.
  4. Initial Tailwind Styling: Use Tailwind CSS in the initial refactor to reduce review/explanation overhead.
  5. $props for Props: Use the $props rune for accessing props in Svelte 5 components.

Theming Vision:

  • Primary Focus: CSS-Based Theming: Site admins should be able to override colors, spacing, etc., using a single theme.css file.
  • Secondary: Template Overrides: Offer a controlled option to override specific component templates.
  • Future Exploration: We'll investigate alternative CSS theming strategies (CSS variables/open props, theming libraries) for more complex scenarios.

Guardrails for Theming:

  1. CSS Changes are Safe: Site admins are responsible for CSS-only theme changes.
  2. Template Override Responsibility: Theme developers are responsible for maintaining template overrides.

This enables:

  • Faster Core Development: We can iterate quickly without worrying about breaking themes.
  • Theme Developer Control: Themes have flexibility but also clear responsibilities.

Theming Hierarchy:

  1. Global CSS Overrides: theme.css for site-wide styling changes.
  2. Component Template Overrides: Replace default templates for specific components.
  3. Route-Level Overrides: Override the entire Page.svelte component for a route.
  4. No Server-Side Theming: Theming changes should not affect +page.server.ts files.

Implementation Stages:

  1. Component-Based Refactoring: Convert routes to the new pattern (one route per PR), keeping existing logic and using Tailwind.
  2. Extract Common Components: Move frequently used components to the $lib folder.
  3. Establish Default Theme: Create the default theme (likely Tailwind-based).
  4. Investigate CSS Theming: Explore advanced CSS theming options (open props, libraries).

hnb-ku avatar Sep 28 '24 09:09 hnb-ku

This is a list to track the current work on stage 1

Unstable:* ( wait to refactor until later )

  • [ ] (app)/[username]/mastodon/+page.svelte
  • [ ] (app)/[username]/+page.svelte
  • [ ] (app)/account/[user_id]/custom-domain/+page.svelte
  • [ ] (app)/account/codeberg/profile/+page.svelte
  • [ ] (app)/account/codeberg/+page.svelte
  • [ ] (app)/account/github/profile/readme/+page.svelte
  • [ ] (app)/account/github/profile/+page.svelte
  • [ ] (app)/account/github/+page.svelte
  • [ ] (app)/account/link-mastodon/+page.svelte
  • [ ] (app)/account/linktree/profile/+page.svelte
  • [ ] (app)/account/linktree/+page.svelte
  • [ ] (app)/account/pages/edit/[slug]/+page.svelte
  • [ ] (app)/account/pages/new/+page.svelte
  • [ ] (app)/account/pages/+page.svelte
  • [ ] (app)/account/zulip/profile/+page.svelte
  • [ ] (app)/account/zulip/+page.svelte

Stable: ( can be refactored now )

  • [x] (app)/[username]/[slug]/+page.svelte
  • [x] (app)/account/forgot-password/+page.svelte
  • [x] (app)/account/register/confirmation/+page.svelte
  • [x] (app)/login/+page.svelte
  • [x] (app)/logout/+page.svelte
  • [ ] (app)/auth/v1/users/[user]/reset/[token]/+page.svelte
  • [x] (app)/auth/v1/users/register/+page.svelte
  • [x] (app)/claim-username/+page.svelte
  • [ ] (app)/connect/discord/[linkId]/+page.svelte
  • [x] (app)/feedback/confirmation/+page.svelte
  • [x] (app)/feedback/+page.svelte
  • [ ] (app)/people/+page.svelte
  • [x] (app)/+layout.svelte
  • [x] (internal)/__internal__/admin/update-username-domains/+page.svelte
  • [x] (internal)/__internal__/admin/+page.svelte
  • [x] (subsites)/subsite/[usernameOrDomain]/+page.svelte

hnb-ku avatar Sep 28 '24 09:09 hnb-ku

  • (app)/[username]/[slug]/+page.svelte

https://github.com/muni-town/weird/pull/188

hnb-ku avatar Sep 28 '24 10:09 hnb-ku

@hnb-ku I feel like the +page.svelte is a little redundant when we have the Page.svelte component.

I think the +page.svelte for most pages would just end up identical to each-other then, right?

I'm totally fine keeping it like that if you think it's a good idea for any reason, I just wanted to double-check.

zicklag avatar Sep 29 '24 00:09 zicklag

I think the +page.svelte for most pages would just end up identical to each-other then, right?

Yes, you're right. We'd just have +page.svelte files that get the data and pass it down to a single top-level component. We just happen to call it Page in the example PR, but I think it's probably better to use something more specific.

The reason behind this is that Svelete "requires" +page.svelte file for it to make that path a "route" (at least that's how I understand it)

Creating a separate "Page" component (that we control inside a routes/components/ folder) allows us to have a "component-loader or resolver" somewhere down the line (not a priority for now).

In other words, a theme can provide its own Page.svelte component for a route and we'll swap it over the default one and pass it the same props without needing to make any changes to svelte's +page.svelte convention.

Additionally, any lingering route logic that needs to happen on the client can be created there. This includes something like client-side transformations (but we still prefer server-side data if possible).

I'm definitely open to any option here and one of the biggest goals is not to bog down core development in any shape of form.

This is something I kind of forgot to mention. For new paths and routes that we add for new features, we don't need to follow the pattern in this issue. Everything can just stay in the +page.svelte file for the first pass of a feature. The next pass can deal with splitting stuff and making it themeable. Themeing is a tertiary concern.

Let me know if this works for you.

hnb-ku avatar Sep 30 '24 12:09 hnb-ku

OK, yeah, that all sounds good. :+1: It's super easy to switch back and forth and isn't hard to understand in either case.

zicklag avatar Sep 30 '24 13:09 zicklag

  • (app)/account/register/confirmation/+page.svelte

https://github.com/muni-town/weird/pull/193

  • (app)/claim-username/+page.svelte

https://github.com/muni-town/weird/pull/194

hnb-ku avatar Oct 02 '24 15:10 hnb-ku

  • (app)/feedback/confirmation/+page.svelte

https://github.com/muni-town/weird/pull/195

  • (app)/feedback/+page.svelte

https://github.com/muni-town/weird/pull/196

hnb-ku avatar Oct 02 '24 16:10 hnb-ku

  • (app)/account/forgot-password/+page.svelte

https://github.com/muni-town/weird/pull/197

  • (app)/auth/v1/users/register/+page.svelte

https://github.com/muni-town/weird/pull/198

hnb-ku avatar Oct 02 '24 18:10 hnb-ku

  • (app)/login/+page.svelte

https://github.com/muni-town/weird/pull/199

hnb-ku avatar Oct 02 '24 19:10 hnb-ku

  • (app)/auth/v1/users/[user]/reset/[token]/+page.svelte

https://github.com/muni-town/weird/pull/200

hnb-ku avatar Oct 02 '24 23:10 hnb-ku