Commit Graph

16 Commits

Author SHA1 Message Date
Félix Malfait b602294f1d Hide the command menu button while the mobile side panel is open (#23471)
On mobile the side panel covers the page, but the page header stays
mounted underneath. Its command menu button (`⌘K`, the `⋮` icon) sits at
the same coordinates as the panel's own close button, so the two icons
render on top of each other.

Measured on a 390x844 viewport with the AI chat open:

- `Command Menu` button at `x=346, y=8, 32x32`
- `Close side panel` button at `x=358, y=14, 24x24`

`SidePanelToggleButton` already hid itself for the command menu and
search pages, but the AI chat pages (`AskAI`, `ViewPreviousAiChats`) are
not in `COMMAND_MENU_SIDE_PANEL_PAGES`, so the button stayed and
overlapped.

## Change

Hide the button on mobile whenever the side panel is open, rather than
enumerating pages — the header is not reachable behind a full-screen
panel either way.

Layout customization mode is the exception and keeps it:
`alignWithSidePanelTopBar` deliberately repositions the button into the
side panel top bar there, so that path is preserved.

Desktop is unaffected.

## Testing

Three cases added to `SidePanelToggleButton.test.tsx` (hidden on mobile
with the panel open, kept on mobile in layout customization mode, kept
on desktop with the AI chat open); the `useIsMobile` mock is now
switchable per test. All 10 tests pass.

Verified in the browser at 390x844: with the AI chat open only `Close
side panel` remains in the top bar, and the button reappears once the
panel is closed.


---
_Generated by [Claude
Code](https://claude.ai/code/session_018gcsCQbuTMsyFWv874p25Q)_

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/23471?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-07-29 09:19:24 +02:00
Raphaël Bosi 62c7e8f6b4 Polish onboarding v2 verify animation and step screens (#22585)
https://github.com/user-attachments/assets/1d9b8dc2-ef01-4202-a97e-b41cab048f87





A few polish tweaks to onboarding v2:

- **Verify/workspace-creation animation:** emphasize the key phrase of
each message in medium weight, the rest regular (e.g. "Creating your
**workspace**…").
- **Wider content column:** 340px → 440px. Collapses to full width on
mobile via the existing `max-width: 100%` on every consumer.
- **Sticky disabled buttons:** step submit buttons now stay disabled
from submit through navigation instead of briefly re-enabling once the
mutation resolves.
- **Fewer pulse loaders:** stop the pulsing logo from flashing when
navigating between onboarding steps (removed the step-page Suspense
fallback loader). The verify animation, cold-boot gates, and sign-in
fallbacks are unchanged.

Note: the reworded activation messages get new Lingui catalog IDs, so
non-English locales fall back to English until catalogs are
re-extracted.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22585?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-07-06 14:44:44 +00:00
Félix Malfait 3aeb2b0d5d Self-host Inter and DM Mono fonts (#22506)
Replaces the two Google Fonts stylesheets with self-hosted fonts via
`@fontsource`, imported in the app entry (and Storybook preview), and
removes the duplicate Inter that BlockNote was shipping.

## Why

- **The caching argument for Google Fonts is dead.** Browsers partition
the HTTP cache by top-level site (Chrome 86+, Firefox 85+, Safari even
earlier), so a font cached from another website is never reused on ours.
Every first-time visitor downloads the fonts either way — Google just
adds a detour.
- **Faster first paint.** This removes two render-blocking cross-origin
stylesheets from `index.html` (DNS + TLS to `fonts.googleapis.com`, then
a second connection to `fonts.gstatic.com`, with no preconnect today).
The fonts now ship from our own `/assets` alongside the rest of the app,
behind the same CDN and cache policy.
- **Privacy.** Visitor IPs are no longer sent to Google on every page
load. A German court ruled in 2022 that Google Fonts embedding violates
GDPR, and privacy-conscious self-hosters currently have no way to opt
out of the dependency.
- **Air-gapped / offline self-hosted instances** currently render
fallback system fonts; they now get the real ones.

## Font unification

We were actually loading Inter from two places: the Google stylesheet,
plus `@blocknote/core/fonts/inter.css` (8 weights, latin-only,
woff+woff2) imported by the two rich-text editors — whichever loaded
last won the cascade. Both are gone; `@fontsource` is now the single
source:

- Inter 400/500/600 (theme weights) + 700 (rich-text bold, previously
only covered by the BlockNote copy)
- DM Mono 400/500 (DM Mono has no 600 upstream; the old Google link
requested one anyway)

Fontsource ships the same `unicode-range` subsets as the Google CSS, so
browsers still only download the subset they need (~60KB of woff2 for
latin), and non-latin locales keep full coverage — which the latin-only
BlockNote copy didn't provide.

## Notes

- The BlockNote PDF export (`exportBlockNoteEditorToPdf.ts`) still
fetches Inter TTFs from `fonts.gstatic.com` at export time — react-pdf
needs TTF files, left unchanged here.


<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22506?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-07-03 10:12:27 +02:00
neo773 323e66433e lint: migrate prettier to oxfmt (#20783)
Most changes are `implements` being unwrapped this is not a oxfmt
regression
Prettier in 3.7 (we're on 3.1) changed this behaviour prettier blog
[post](https://prettier.io/blog/2025/11/27/3.7.0#change-18094)

This unifies our linting tooling

---------

Co-authored-by: github-actions <github-actions@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2026-05-22 00:21:33 +02:00
Charles Bochet c41a8e2b23 [DevXP] Simplify twenty-ui theme system: replace auto-generated files with static CSS variables (#18389)
## Summary

Now that Twenty has fully migrated from Emotion to Linaria, the theme
system has been simplified to remove unnecessary complexity that existed
only to support the old runtime injection pattern.

### What changed

- **Deleted** `generateThemeConstants.ts` script and the entire
`generated/` directory — no more auto-generation
- **Added** `theme-light.css` and `theme-dark.css`: static CSS files
with 991 custom properties each, scoped under `.light` and `.dark`
selectors respectively
- **Moved** `themeCssVariables.ts` out of `generated/` and hand-maintain
it as a static `as const` object of `var(--t-*)` references (Linaria can
statically evaluate these at build time)
- **Extracted** numeric constants (`MOBILE_VIEWPORT`, `ICON_SIZES`,
`ICON_STROKES`) into a new `constants.ts` — CSS variables can't be used
in media queries or as numeric icon size props
- **Simplified** `ThemeContextProvider`: removed
`ThemeCssVariableInjectorEffect` entirely; now uses a single
`useLayoutEffect` to toggle `.light`/`.dark` class on `<html>`
- **Added** `class="light"` to `index.html` as default to prevent FOUC
before React hydration

### Why

The previous setup maintained a dual system: JS theme objects
(`THEME_LIGHT`/`THEME_DARK`) used at runtime, plus a generation script
that produced CSS variable entry arrays, which were then injected into
the DOM by `ThemeCssVariableInjectorEffect`. With Linaria, theme values
only need to be CSS custom properties — the JS objects were redundant.
This PR removes ~250 lines of infrastructure while keeping the same
theming capabilities.
2026-03-04 23:30:25 +01:00
martmull 158a7a89d5 1859 extensibility improve application settings section (#16786)
## After
<img width="934" height="750" alt="image"
src="https://github.com/user-attachments/assets/f2d7f743-fa4f-4e7d-a060-033f6087e4b6"
/>
<img width="1008" height="652" alt="image"
src="https://github.com/user-attachments/assets/3d36bfae-aa30-4946-88f2-e99bf074f768"
/>
2025-12-24 14:35:36 +01:00
neo773 af835e23be fix: sync color scheme on loading state (#13878)
Before:


https://github.com/user-attachments/assets/a769a2f8-554a-42f7-8adb-e8b4be92a4d1


Aftter:


https://github.com/user-attachments/assets/9200967a-902f-4f8d-822d-827dda32bac2

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
2025-08-12 22:47:58 +02:00
Félix Malfait 05adad4648 Fix incorrect relative path (#12582)
Not sure why we didn't see it before but I see errors in the console on
staging when trying to load the manifest.json
2025-06-13 08:09:06 +02:00
Félix Malfait 5343dd62d6 Update readme with partner logos (#11722)
Recognize the role of Greptile/Sentry/Crowdin/Chromatic which give
generous open source plans + some cleanup
2025-04-24 16:09:43 +02:00
Charles Bochet b6e344e7be Various fixes (#11448)
# Scrollbar fix

Fixes https://github.com/twentyhq/twenty/issues/11403

<img width="1512" alt="image"
src="https://github.com/user-attachments/assets/b13fe0f2-8c61-4ea8-9ea1-e61e571a90da"
/>

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2025-04-09 01:03:43 +02:00
Paul Rastoin d6171c66df [BUGFIX] Dynamic default body background depending on device preferences (#10626)
# Introduction
close #9965 

When landing on twenty you should be able to see a white screen
flickering if you had setup dark mode.
This is because before the SPA has been loaded we're not displaying
anything, which in a white screen from the browser.
During this period we should display a background color following the
user's device theme.

## Reproduction
In order to reproduce this behavior define a fast 4G connection from
your network console.

## Cons
Device mode might not the one chosen afterwards when the user has been
authenticated
=> We should store appearance settings in the local storage in order to
optimistically render the default "loading" background ( wouldn't be
100% bullet proof for instance if the user is now unauth for some reason
)

Body background will be override by theme after app bootstrap
2025-03-04 15:54:16 +01:00
Charles Bochet 64938d5a05 Refactor RecordPicker part 2 (#10502)
Keep clarifying folders:
- record-picker is now clean
- record-picker-morph-legacy contains activityTarget logic that will be
abstracted later
2025-02-26 13:54:16 +01:00
Félix Malfait e5754d2152 Remove env-config.js (#9331)
Fixes #5340 which had been open for a long time
2025-01-03 15:18:02 +01:00
Mohammed Abdul Razak Wahab 08a9db2df6 Add Twenty Shared & Fix profile image rendering (#8841)
PR Summary: 

1. Added `Twenty Shared` Package to centralize utilitiies as mentioned
in #8942
2. Optimization of `getImageAbsoluteURI.ts` to handle edge cases


![image](https://github.com/user-attachments/assets/c72a3061-6eba-46b8-85ac-869f06bf23c0)

---------

Co-authored-by: Antoine Moreaux <moreaux.antoine@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-12-17 09:24:21 +01:00
Baptiste Devessier 898006f89d Prevent automatic zoom when focusing inputs on iOS (#8477)
This is the result of a long discussion we had here:
https://github.com/twentyhq/twenty/issues/8001.

The goal is to stop iOS from automatically zooming when the user focuses
on an input whose font size is less than 16px.

The options were:

1. Disable zoom for all devices
2. Disable zoom for devices detected as iOS devices, which doesn't
prevent users from zooming manually but fixes the auto-zoom bug
3. Set the font size of the inputs to be equal to or greater than
16px—this change would take a lot of time

To me, the second option is the best, as iOS prevents developers from
disabling zoom. They saw that it was overused and chose to restrict this
setting. Setting a `maximum-scale` doesn't prevent users from zooming,
but it fixes the initial bug we had.

My implementation can be seen as [progressive
enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement
): If we can detect that the user uses an iOS device, we'll set the
`maximum-scale` viewport property. Relying on the user agent is always
unstable, and the check might fail unpredictably. We might not disallow
auto-zoom for some iOS devices.

However, I think we can either:

- Invest some time to choose a more reliable user detection pattern if
the one I suggest is not sufficient ([we find many different checks on
the
internet](https://stackoverflow.com/questions/9038625/detect-if-device-is-ios),
I'm not sure which one is the best)
- Choose to apply the viewport setting to all devices and remove the JS
code. According to my tests, it doesn't prevent zooming on desktops.
However, it does on Android phones. I think it's not lovely to disallow
zoom, but if the team agrees that we should go this way, I won't
disagree.

I know my JavaScript code does not follow a pattern we want to spread in
the app. The synchronous script will run as soon as possible to ensure
the viewport is correctly set when the website launches. This shouldn't
be an example followed by others.

Thanks, @harshit078, for your help in thinking about the best option.

I'm tagging @lucasbordeau and @charlesBochet for a technical review.

I would appreciate if someone could test on a more recent iOS device
than mine.

Here is a demonstration of the behavior on iOS:


https://github.com/user-attachments/assets/d49fb65f-dd76-455c-9ac0-d4c002a7fe89
2024-11-13 15:34:20 +01:00
Charles Bochet 5bdca9de6c Migrate to a monorepo structure (#2909) 2023-12-10 18:10:54 +01:00