diff --git a/app.json b/app.json
index 3f3eb56..6b0b814 100644
--- a/app.json
+++ b/app.json
@@ -21,7 +21,6 @@
"package": "com.anonymous.bahla"
},
"web": {
- "bundler": "metro",
"output": "static",
"favicon": "./assets/images/favicon.png"
},
diff --git a/babel.config.js b/babel.config.js
deleted file mode 100644
index f3c649b..0000000
--- a/babel.config.js
+++ /dev/null
@@ -1,9 +0,0 @@
-module.exports = function (api) {
- api.cache(true);
- return {
- presets: [
- ["babel-preset-expo", { jsxImportSource: "nativewind" }],
- "nativewind/babel",
- ],
- };
-};
diff --git a/metro.config.js b/metro.config.js
deleted file mode 100644
index 9800736..0000000
--- a/metro.config.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Learn more https://docs.expo.io/guides/customizing-metro
-const { getDefaultConfig } = require('expo/metro-config');
-const { withNativeWind } = require('nativewind/metro');
-
-/** @type {import('expo/metro-config').MetroConfig} */
-const config = getDefaultConfig(__dirname);
-
-module.exports = withNativeWind(config, { input: './src/global.css' })
diff --git a/nativewind-env.d.ts b/nativewind-env.d.ts
deleted file mode 100644
index fbca8c7..0000000
--- a/nativewind-env.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-///
\ No newline at end of file
diff --git a/output.css b/output.css
deleted file mode 100644
index a5b53bf..0000000
--- a/output.css
+++ /dev/null
@@ -1,608 +0,0 @@
-*, ::before, ::after {
- --tw-border-spacing-x: 0;
- --tw-border-spacing-y: 0;
- --tw-translate-x: 0;
- --tw-translate-y: 0;
- --tw-rotate: 0;
- --tw-skew-x: 0;
- --tw-skew-y: 0;
- --tw-scale-x: 1;
- --tw-scale-y: 1;
- --tw-pan-x: ;
- --tw-pan-y: ;
- --tw-pinch-zoom: ;
- --tw-scroll-snap-strictness: proximity;
- --tw-gradient-from-position: ;
- --tw-gradient-via-position: ;
- --tw-gradient-to-position: ;
- --tw-ordinal: ;
- --tw-slashed-zero: ;
- --tw-numeric-figure: ;
- --tw-numeric-spacing: ;
- --tw-numeric-fraction: ;
- --tw-ring-inset: ;
- --tw-ring-offset-width: 0px;
- --tw-ring-offset-color: #fff;
- --tw-ring-color: rgb(59 130 246 / 0.5);
- --tw-ring-offset-shadow: 0 0 #0000;
- --tw-ring-shadow: 0 0 #0000;
- --tw-shadow: 0 0 #0000;
- --tw-shadow-colored: 0 0 #0000;
- --tw-blur: ;
- --tw-brightness: ;
- --tw-contrast: ;
- --tw-grayscale: ;
- --tw-hue-rotate: ;
- --tw-invert: ;
- --tw-saturate: ;
- --tw-sepia: ;
- --tw-drop-shadow: ;
- --tw-backdrop-blur: ;
- --tw-backdrop-brightness: ;
- --tw-backdrop-contrast: ;
- --tw-backdrop-grayscale: ;
- --tw-backdrop-hue-rotate: ;
- --tw-backdrop-invert: ;
- --tw-backdrop-opacity: ;
- --tw-backdrop-saturate: ;
- --tw-backdrop-sepia: ;
- --tw-contain-size: ;
- --tw-contain-layout: ;
- --tw-contain-paint: ;
- --tw-contain-style: ;
-}
-
-::backdrop {
- --tw-border-spacing-x: 0;
- --tw-border-spacing-y: 0;
- --tw-translate-x: 0;
- --tw-translate-y: 0;
- --tw-rotate: 0;
- --tw-skew-x: 0;
- --tw-skew-y: 0;
- --tw-scale-x: 1;
- --tw-scale-y: 1;
- --tw-pan-x: ;
- --tw-pan-y: ;
- --tw-pinch-zoom: ;
- --tw-scroll-snap-strictness: proximity;
- --tw-gradient-from-position: ;
- --tw-gradient-via-position: ;
- --tw-gradient-to-position: ;
- --tw-ordinal: ;
- --tw-slashed-zero: ;
- --tw-numeric-figure: ;
- --tw-numeric-spacing: ;
- --tw-numeric-fraction: ;
- --tw-ring-inset: ;
- --tw-ring-offset-width: 0px;
- --tw-ring-offset-color: #fff;
- --tw-ring-color: rgb(59 130 246 / 0.5);
- --tw-ring-offset-shadow: 0 0 #0000;
- --tw-ring-shadow: 0 0 #0000;
- --tw-shadow: 0 0 #0000;
- --tw-shadow-colored: 0 0 #0000;
- --tw-blur: ;
- --tw-brightness: ;
- --tw-contrast: ;
- --tw-grayscale: ;
- --tw-hue-rotate: ;
- --tw-invert: ;
- --tw-saturate: ;
- --tw-sepia: ;
- --tw-drop-shadow: ;
- --tw-backdrop-blur: ;
- --tw-backdrop-brightness: ;
- --tw-backdrop-contrast: ;
- --tw-backdrop-grayscale: ;
- --tw-backdrop-hue-rotate: ;
- --tw-backdrop-invert: ;
- --tw-backdrop-opacity: ;
- --tw-backdrop-saturate: ;
- --tw-backdrop-sepia: ;
- --tw-contain-size: ;
- --tw-contain-layout: ;
- --tw-contain-paint: ;
- --tw-contain-style: ;
-}
-
-/*
-! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com
-*/
-
-/*
-1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
-2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
-*/
-
-*,
-::before,
-::after {
- box-sizing: border-box;
- /* 1 */
- border-width: 0;
- /* 2 */
- border-style: solid;
- /* 2 */
- border-color: #e5e7eb;
- /* 2 */
-}
-
-::before,
-::after {
- --tw-content: '';
-}
-
-/*
-1. Use a consistent sensible line-height in all browsers.
-2. Prevent adjustments of font size after orientation changes in iOS.
-3. Use a more readable tab size.
-4. Use the user's configured `sans` font-family by default.
-5. Use the user's configured `sans` font-feature-settings by default.
-6. Use the user's configured `sans` font-variation-settings by default.
-7. Disable tap highlights on iOS
-*/
-
-html,
-:host {
- line-height: 1.5;
- /* 1 */
- -webkit-text-size-adjust: 100%;
- /* 2 */
- -moz-tab-size: 4;
- /* 3 */
- -o-tab-size: 4;
- tab-size: 4;
- /* 3 */
- font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
- /* 4 */
- font-feature-settings: normal;
- /* 5 */
- font-variation-settings: normal;
- /* 6 */
- -webkit-tap-highlight-color: transparent;
- /* 7 */
-}
-
-/*
-1. Remove the margin in all browsers.
-2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
-*/
-
-body {
- margin: 0;
- /* 1 */
- line-height: inherit;
- /* 2 */
-}
-
-/*
-1. Add the correct height in Firefox.
-2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
-3. Ensure horizontal rules are visible by default.
-*/
-
-hr {
- height: 0;
- /* 1 */
- color: inherit;
- /* 2 */
- border-top-width: 1px;
- /* 3 */
-}
-
-/*
-Add the correct text decoration in Chrome, Edge, and Safari.
-*/
-
-abbr:where([title]) {
- -webkit-text-decoration: underline dotted;
- text-decoration: underline dotted;
-}
-
-/*
-Remove the default font size and weight for headings.
-*/
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- font-size: inherit;
- font-weight: inherit;
-}
-
-/*
-Reset links to optimize for opt-in styling instead of opt-out.
-*/
-
-a {
- color: inherit;
- text-decoration: inherit;
-}
-
-/*
-Add the correct font weight in Edge and Safari.
-*/
-
-b,
-strong {
- font-weight: bolder;
-}
-
-/*
-1. Use the user's configured `mono` font-family by default.
-2. Use the user's configured `mono` font-feature-settings by default.
-3. Use the user's configured `mono` font-variation-settings by default.
-4. Correct the odd `em` font sizing in all browsers.
-*/
-
-code,
-kbd,
-samp,
-pre {
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
- /* 1 */
- font-feature-settings: normal;
- /* 2 */
- font-variation-settings: normal;
- /* 3 */
- font-size: 1em;
- /* 4 */
-}
-
-/*
-Add the correct font size in all browsers.
-*/
-
-small {
- font-size: 80%;
-}
-
-/*
-Prevent `sub` and `sup` elements from affecting the line height in all browsers.
-*/
-
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-
-sub {
- bottom: -0.25em;
-}
-
-sup {
- top: -0.5em;
-}
-
-/*
-1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
-2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
-3. Remove gaps between table borders by default.
-*/
-
-table {
- text-indent: 0;
- /* 1 */
- border-color: inherit;
- /* 2 */
- border-collapse: collapse;
- /* 3 */
-}
-
-/*
-1. Change the font styles in all browsers.
-2. Remove the margin in Firefox and Safari.
-3. Remove default padding in all browsers.
-*/
-
-button,
-input,
-optgroup,
-select,
-textarea {
- font-family: inherit;
- /* 1 */
- font-feature-settings: inherit;
- /* 1 */
- font-variation-settings: inherit;
- /* 1 */
- font-size: 100%;
- /* 1 */
- font-weight: inherit;
- /* 1 */
- line-height: inherit;
- /* 1 */
- letter-spacing: inherit;
- /* 1 */
- color: inherit;
- /* 1 */
- margin: 0;
- /* 2 */
- padding: 0;
- /* 3 */
-}
-
-/*
-Remove the inheritance of text transform in Edge and Firefox.
-*/
-
-button,
-select {
- text-transform: none;
-}
-
-/*
-1. Correct the inability to style clickable types in iOS and Safari.
-2. Remove default button styles.
-*/
-
-button,
-input:where([type='button']),
-input:where([type='reset']),
-input:where([type='submit']) {
- -webkit-appearance: button;
- /* 1 */
- background-color: transparent;
- /* 2 */
- background-image: none;
- /* 2 */
-}
-
-/*
-Use the modern Firefox focus style for all focusable elements.
-*/
-
-:-moz-focusring {
- outline: auto;
-}
-
-/*
-Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
-*/
-
-:-moz-ui-invalid {
- box-shadow: none;
-}
-
-/*
-Add the correct vertical alignment in Chrome and Firefox.
-*/
-
-progress {
- vertical-align: baseline;
-}
-
-/*
-Correct the cursor style of increment and decrement buttons in Safari.
-*/
-
-::-webkit-inner-spin-button,
-::-webkit-outer-spin-button {
- height: auto;
-}
-
-/*
-1. Correct the odd appearance in Chrome and Safari.
-2. Correct the outline style in Safari.
-*/
-
-[type='search'] {
- -webkit-appearance: textfield;
- /* 1 */
- outline-offset: -2px;
- /* 2 */
-}
-
-/*
-Remove the inner padding in Chrome and Safari on macOS.
-*/
-
-::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-
-/*
-1. Correct the inability to style clickable types in iOS and Safari.
-2. Change font properties to `inherit` in Safari.
-*/
-
-::-webkit-file-upload-button {
- -webkit-appearance: button;
- /* 1 */
- font: inherit;
- /* 2 */
-}
-
-/*
-Add the correct display in Chrome and Safari.
-*/
-
-summary {
- display: list-item;
-}
-
-/*
-Removes the default spacing and border for appropriate elements.
-*/
-
-blockquote,
-dl,
-dd,
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-hr,
-figure,
-p,
-pre {
- margin: 0;
-}
-
-fieldset {
- margin: 0;
- padding: 0;
-}
-
-legend {
- padding: 0;
-}
-
-ol,
-ul,
-menu {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-/*
-Reset default styling for dialogs.
-*/
-
-dialog {
- padding: 0;
-}
-
-/*
-Prevent resizing textareas horizontally by default.
-*/
-
-textarea {
- resize: vertical;
-}
-
-/*
-1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
-2. Set the default placeholder color to the user's configured gray 400 color.
-*/
-
-input::-moz-placeholder, textarea::-moz-placeholder {
- opacity: 1;
- /* 1 */
- color: #9ca3af;
- /* 2 */
-}
-
-input::placeholder,
-textarea::placeholder {
- opacity: 1;
- /* 1 */
- color: #9ca3af;
- /* 2 */
-}
-
-/*
-Set the default cursor for buttons.
-*/
-
-button,
-[role="button"] {
- cursor: pointer;
-}
-
-/*
-Make sure disabled buttons don't get the pointer cursor.
-*/
-
-:disabled {
- cursor: default;
-}
-
-/*
-1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
-2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
- This can trigger a poorly considered lint error in some tools but is included by design.
-*/
-
-img,
-svg,
-video,
-canvas,
-audio,
-iframe,
-embed,
-object {
- display: block;
- /* 1 */
- vertical-align: middle;
- /* 2 */
-}
-
-/*
-Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
-*/
-
-img,
-video {
- max-width: 100%;
- height: auto;
-}
-
-/* Make elements with the HTML hidden attribute stay hidden by default */
-
-[hidden]:where(:not([hidden="until-found"])) {
- display: none;
-}
-
-:root {
- --css-interop-darkMode: media;
- --css-interop: true;
- --css-interop-nativewind: true;
-}
-
-.container {
- width: 100%;
-}
-
-@media (min-width: 640px) {
- .container {
- max-width: 640px;
- }
-}
-
-@media (min-width: 768px) {
- .container {
- max-width: 768px;
- }
-}
-
-@media (min-width: 1024px) {
- .container {
- max-width: 1024px;
- }
-}
-
-@media (min-width: 1280px) {
- .container {
- max-width: 1280px;
- }
-}
-
-@media (min-width: 1536px) {
- .container {
- max-width: 1536px;
- }
-}
-
-.flex {
- display: flex;
-}
-
-.bg-blue-500 {
- --tw-bg-opacity: 1;
- background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));
-}
-
-.font-bold {
- font-weight: 700;
-}
\ No newline at end of file
diff --git a/package.json b/package.json
index 9fceb80..e8866bf 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,6 @@
"@react-navigation/bottom-tabs": "^7.18.18",
"@tanstack/react-query": "^5.102.8",
"axios": "^1.20.0",
- "babel-preset-expo": "^57.0.9",
"expo": "~56.0.5",
"expo-blur": "~56.0.4",
"expo-constants": "~56.0.16",
@@ -31,8 +30,6 @@
"expo-web-browser": "~56.0.5",
"lucide-react": "^1.38.0",
"lucide-react-native": "^1.38.0",
- "nativewind": "^4.2.6",
- "prettier-plugin-tailwindcss": "^0.5.14",
"react": "19.2.3",
"react-dom": "19.2.3",
"react-native": "0.85.3",
@@ -43,7 +40,6 @@
"react-native-svg": "15.15.4",
"react-native-web": "~0.21.0",
"react-native-worklets": "0.8.3",
- "tailwindcss": "^3.4.19",
"zod": "^4.5.4",
"zustand": "^5.0.15"
},
diff --git a/src/app/(tabs)/my-events.tsx b/src/app/(tabs)/my-events.tsx
index 0574acc..4084b00 100644
--- a/src/app/(tabs)/my-events.tsx
+++ b/src/app/(tabs)/my-events.tsx
@@ -1,15 +1,22 @@
import { StyleSheet, Text, View } from 'react-native';
+import { Header } from '@/components/ui/Header';
+import { Screen } from '@/components/ui/Screen';
+
import { colors } from '@/theme/colors';
import { spacing } from '@/theme/spacing';
import { typography } from '@/theme/typography';
export default function MyEventsTabScreen() {
return (
-
- My Events
- Base ecran mes events
-
+
+
+
+
+ My Events
+ Base ecran mes events
+
+
);
}
diff --git a/src/app/index-old.tsx b/src/app/index-old.tsx
index abe6a73..ac3aad7 100644
--- a/src/app/index-old.tsx
+++ b/src/app/index-old.tsx
@@ -10,8 +10,6 @@ import { colors } from '@/theme/colors';
import { spacing } from '@/theme/spacing';
import { typography } from '@/theme/typography';
-import '../global.css';
-
export default function Index() {
const [selectedThemes, setSelectedThemes] = useState(['Soirée', 'Techno', 'Festival']);
diff --git a/src/components/navigation/BahlaTabBar copy.tsx b/src/components/navigation/BahlaTabBar copy.tsx
new file mode 100644
index 0000000..81971d5
--- /dev/null
+++ b/src/components/navigation/BahlaTabBar copy.tsx
@@ -0,0 +1,278 @@
+/* ------------------------------------------------------------------ *
+ * BahlaTabBar — barre d'onglets floutée, partagée par (tabs) et (org).
+ *
+ * Une seule implémentation pour les deux parcours : le verre dépoli,
+ * le calcul de safe area, le rendu des items et l'accessibilité sont
+ * identiques. Seul le bouton central change, et il est optionnel.
+ *
+ * Usage :
+ * }> // utilisateur
+ * }>
+ *
+ * Dépendances : expo-blur · expo-linear-gradient ·
+ * react-native-safe-area-context · react-native-svg
+ * ------------------------------------------------------------------ */
+import { BlurView } from 'expo-blur';
+import { LinearGradient } from 'expo-linear-gradient';
+import { Tabs } from 'expo-router';
+import { useCallback, type ComponentProps } from 'react';
+import {
+ Platform,
+ Pressable,
+ StyleSheet,
+ Text,
+ View,
+ type ViewStyle,
+} from 'react-native';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+
+import { colors, gradientDirection, gradients } from '@/theme/colors';
+import { fontFamily, typography } from '@/theme/typography';
+import { Plus } from 'lucide-react-native';
+
+/** Hauteur de la barre hors safe area. La hauteur réelle y ajoute l'inset bas. */
+export const TAB_BAR_BASE_HEIGHT = 52;
+const FAB_SIZE = 62;
+
+/**
+ * expo-blur ne rend rien d'exploitable sous Android 9 : sans ce repli on
+ * obtient un rectangle transparent et des libellés illisibles.
+ */
+const SUPPORTS_BLUR = Platform.OS === 'ios' || Number(Platform.Version) >= 28;
+
+type ExpoRouterTabBarProps = Parameters<
+ NonNullable['tabBar']>
+>[0];
+
+type Props = ExpoRouterTabBarProps & {
+ /**
+ * Nom de la route factice qui occupe l'emplacement central.
+ * Absent côté utilisateur — il n'y a pas de bouton flottant.
+ */
+ fabRouteName?: string;
+ /** Appelé à la place d'une navigation quand on presse le bouton central. */
+ onFabPress?: () => void;
+ /** Libellé lu par les lecteurs d'écran sur le bouton central. */
+ fabAccessibilityLabel?: string;
+};
+
+export function BahlaTabBar({
+ state,
+ descriptors,
+ navigation,
+ fabRouteName,
+ onFabPress,
+ fabAccessibilityLabel = 'Créer',
+}: Props) {
+ const insets = useSafeAreaInsets();
+
+ const handlePress = useCallback(
+ (routeKey: string, routeName: string, isFocused: boolean) => {
+ const event = navigation.emit({
+ type: 'tabPress',
+ target: routeKey,
+ canPreventDefault: true,
+ });
+ if (isFocused || event.defaultPrevented) return;
+ navigation.navigate(routeName as never);
+ },
+ [navigation],
+ );
+
+ const handleLongPress = useCallback(
+ (routeKey: string) => {
+ navigation.emit({ type: 'tabLongPress', target: routeKey });
+ },
+ [navigation],
+ );
+
+ return (
+
+ {state.routes.map((route: (typeof state.routes)[number], index: number) => {
+ const { options } = descriptors[route.key];
+ const isFocused = state.index === index;
+ const tint = isFocused ? colors.primary : colors.textSecondary;
+
+ /* --- Emplacement central : bouton flottant, pas un onglet ---- */
+ if (fabRouteName && route.name === fabRouteName) {
+ return (
+
+ [
+ styles.fab,
+ pressed && styles.fabPressed,
+ ]}
+ >
+
+
+
+
+
+ );
+ }
+
+ /* --- Onglet ordinaire ---------------------------------------- */
+ const label =
+ typeof options.tabBarLabel === 'string'
+ ? options.tabBarLabel
+ : (options.title ?? route.name);
+
+ return (
+ handlePress(route.key, route.name, isFocused)}
+ onLongPress={() => handleLongPress(route.key)}
+ style={styles.item}
+ >
+
+ {options.tabBarIcon?.({
+ focused: isFocused,
+ color: tint,
+ size: 23,
+ })}
+ {options.tabBarBadge != null && (
+
+
+ {options.tabBarBadge}
+
+
+ )}
+
+
+ {label}
+
+
+ );
+ })}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ bar: {
+ position: 'absolute',
+ left: 0,
+ right: 0,
+ bottom: 0,
+ flexDirection: 'row',
+ alignItems: 'flex-start',
+ paddingTop: 8,
+ borderTopWidth: StyleSheet.hairlineWidth * 2,
+ borderTopColor: colors.border,
+ overflow: 'visible',
+ } as ViewStyle,
+
+ item: {
+ flex: 1,
+ alignItems: 'center',
+ gap: 5,
+ // La zone tactile couvre toute la hauteur de la barre.
+ alignSelf: 'stretch',
+ paddingTop: 2,
+ },
+
+ label: {
+ ...typography.tabLabel,
+ fontFamily: undefined, // remplacé plus haut selon l'état
+ },
+
+ badge: {
+ position: 'absolute',
+ top: -4,
+ right: -8,
+ minWidth: 16,
+ height: 16,
+ paddingHorizontal: 4,
+ borderRadius: 999,
+ backgroundColor: colors.primary,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+
+ badgeText: {
+ ...typography.overlineSm,
+ fontSize: 9,
+ lineHeight: 16,
+ letterSpacing: 0,
+ color: colors.onPrimary,
+ },
+
+ /* Le créneau central est plus étroit que les onglets : 84 px fixes,
+ comme la colonne du même nom dans la maquette. */
+ fabSlot: {
+ width: 84,
+ alignItems: 'center',
+ },
+
+ fab: {
+ width: FAB_SIZE,
+ height: FAB_SIZE,
+ aspectRatio: 1,
+ borderRadius: 15,
+ // Remonte au-dessus de la barre et découpe un anneau dans le fond.
+ marginTop: -30,
+ overflow: 'hidden',
+ alignSelf: 'center',
+ borderWidth: 3,
+ borderColor: colors.deepBackground,
+ shadowColor: colors.primary,
+ shadowOffset: { width: 0, height: 14 },
+ shadowOpacity: 0.85,
+ shadowRadius: 17,
+ elevation: 12,
+ },
+
+ fabPressed: {
+ transform: [{ scale: 0.94 }],
+ shadowOpacity: 0.5,
+ },
+
+ fabGradient: {
+ width: '100%',
+ height: '100%',
+ aspectRatio: 1,
+ borderRadius: 15,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+});
+
+export default BahlaTabBar;
diff --git a/src/components/navigation/BahlaTabBar.tsx b/src/components/navigation/BahlaTabBar.tsx
index 2ab060b..b95a093 100644
--- a/src/components/navigation/BahlaTabBar.tsx
+++ b/src/components/navigation/BahlaTabBar.tsx
@@ -13,17 +13,15 @@
* Dépendances : expo-blur · expo-linear-gradient ·
* react-native-safe-area-context · react-native-svg
* ------------------------------------------------------------------ */
-import { BlurView } from 'expo-blur';
import { LinearGradient } from 'expo-linear-gradient';
import { Tabs } from 'expo-router';
import { useCallback, type ComponentProps } from 'react';
import {
- Platform,
Pressable,
StyleSheet,
Text,
View,
- type ViewStyle,
+ type ViewStyle
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
@@ -33,13 +31,9 @@ import { Plus } from 'lucide-react-native';
/** Hauteur de la barre hors safe area. La hauteur réelle y ajoute l'inset bas. */
export const TAB_BAR_BASE_HEIGHT = 52;
-const FAB_SIZE = 62;
-
-/**
- * expo-blur ne rend rien d'exploitable sous Android 9 : sans ce repli on
- * obtient un rectangle transparent et des libellés illisibles.
- */
-const SUPPORTS_BLUR = Platform.OS === 'ios' || Number(Platform.Version) >= 28;
+const FAB_SIZE = 72;
+const FAB_RADIUS = 24;
+const FAB_LIFT = 40;
type ExpoRouterTabBarProps = Parameters<
NonNullable['tabBar']>
@@ -88,18 +82,13 @@ export function BahlaTabBar({
);
return (
-
@@ -112,24 +101,28 @@ export function BahlaTabBar({
if (fabRouteName && route.name === fabRouteName) {
return (
+
[
- styles.fab,
- pressed && styles.fabPressed,
- ]}
+ style={styles.fabPressable}
>
-
-
-
+ {({ pressed }) => (
+
+
+
+ )}
+
);
}
@@ -181,7 +174,7 @@ export function BahlaTabBar({
);
})}
-
+
);
}
@@ -237,41 +230,51 @@ const styles = StyleSheet.create({
/* Le créneau central est plus étroit que les onglets : 84 px fixes,
comme la colonne du même nom dans la maquette. */
fabSlot: {
- width: 84,
+ width: 96,
alignItems: 'center',
+ overflow: 'visible',
+ zIndex: 20,
},
- fab: {
+ fabShell: {
width: FAB_SIZE,
height: FAB_SIZE,
aspectRatio: 1,
- borderRadius: 15,
+ borderRadius: FAB_RADIUS,
// Remonte au-dessus de la barre et découpe un anneau dans le fond.
- marginTop: -30,
+ marginTop: -FAB_LIFT,
overflow: 'hidden',
alignSelf: 'center',
+ zIndex: 20,
borderWidth: 3,
borderColor: colors.deepBackground,
shadowColor: colors.primary,
- shadowOffset: { width: 0, height: 14 },
- shadowOpacity: 0.85,
- shadowRadius: 17,
- elevation: 12,
+ shadowOffset: { width: 0, height: 16 },
+ shadowOpacity: 0.9,
+ shadowRadius: 20,
+ elevation: 18,
},
- fabPressed: {
- transform: [{ scale: 0.94 }],
- shadowOpacity: 0.5,
+ fabPressable: {
+ width: '100%',
+ height: '100%',
+ borderRadius: FAB_RADIUS,
+ overflow: 'hidden',
},
fabGradient: {
width: '100%',
height: '100%',
aspectRatio: 1,
- borderRadius: 15,
+ borderRadius: FAB_RADIUS,
alignItems: 'center',
justifyContent: 'center',
},
+
+ fabGradientPressed: {
+ transform: [{ scale: 0.96 }],
+ opacity: 0.92,
+ },
});
export default BahlaTabBar;
diff --git a/src/components/organizer/CreateActionSheet.tsx b/src/components/organizer/CreateActionSheet.tsx
index 3ec5ad7..c03b834 100644
--- a/src/components/organizer/CreateActionSheet.tsx
+++ b/src/components/organizer/CreateActionSheet.tsx
@@ -4,18 +4,18 @@
* ------------------------------------------------------------------ */
import { LinearGradient } from 'expo-linear-gradient';
import {
- Modal,
- Pressable,
- StyleSheet,
- Text,
- View,
- type ViewStyle,
+ Modal,
+ Pressable,
+ StyleSheet,
+ Text,
+ View,
+ type ViewStyle,
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { colors, gradientDirection, gradients } from '@/theme/colors';
import { typography } from '@/theme/typography';
-import { Plus } from 'lucide-react-native';
+import { MessageSquare, Plus } from 'lucide-react-native';
type Props = {
visible: boolean;
@@ -32,6 +32,7 @@ export function CreateActionSheet({
}: Props) {
const insets = useSafeAreaInsets();
+ /* TODO - rendre dynamique en fonction du club connecté */
return (
+
+
+ Créer - Club Vertige
+
+
+
+
[styles.row, pressed && styles.rowPressed]}
+ style={styles.rowPressable}
>
-
-
-
-
- Créer un événement
- Date, lieu, line-up, billetterie
-
+ {({ pressed }) => (
+
+
+
+
+
+ Créer un événement
+ Date, lieu, line-up, billetterie
+
+
+ )}
[styles.row, pressed && styles.rowPressed]}
+ style={styles.rowPressable}
>
-
-
-
-
- Publier un post
- Sur un de tes événements à venir
-
+ {({ pressed }) => (
+
+
+
+
+
+ Publier un post
+ Sur un de tes événements à venir
+
+
+ )}
@@ -117,7 +138,13 @@ const styles = StyleSheet.create({
borderColor: colors.border,
},
- rowPressed: { opacity: 0.7 },
+ rowPressable: {
+ borderRadius: 18,
+ },
+
+ rowPressed: {
+ opacity: 0.7,
+ },
iconBox: {
width: 48,
@@ -133,6 +160,13 @@ const styles = StyleSheet.create({
borderColor: colors.border,
},
+ modalTitle: {
+ ...typography.sectionLabel,
+ color: colors.textPrimary,
+ fontSize: 14,
+ marginBottom: 10,
+ },
+
rowText: { flex: 1, gap: 2 },
rowTitle: {
diff --git a/src/components/ui/Header.tsx b/src/components/ui/Header.tsx
new file mode 100644
index 0000000..2c0c8ab
--- /dev/null
+++ b/src/components/ui/Header.tsx
@@ -0,0 +1,91 @@
+/* ------------------------------------------------------------------ *
+ * Header — trois variantes : large, compact, overlay.
+ * ------------------------------------------------------------------ */
+import { useRouter } from 'expo-router';
+import { ChevronLeft } from 'lucide-react-native';
+import { ReactNode } from 'react';
+import { Pressable, StyleSheet, Text, View } from 'react-native';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+
+import { colors } from '@/theme/colors';
+import { typography } from '@/theme/typography';
+
+type Props = {
+ title?: string;
+ /** Overline mono au-dessus du titre (variante large uniquement). */
+ overline?: string;
+ variant?: 'large' | 'compact' | 'overlay';
+ /** Flèche retour. Auto : true sauf en `large`. */
+ back?: boolean;
+ onBack?: () => void;
+ /** Actions à droite — icônes 44×44 déjà encapsulées par l'appelant. */
+ right?: ReactNode;
+};
+
+export function Header({ title, overline, variant = 'large', back, onBack, right }: Props) {
+ const router = useRouter();
+ const insets = useSafeAreaInsets();
+ const showBack = back ?? variant !== 'large';
+ const glass = variant === 'overlay';
+
+ return (
+
+ {showBack && (
+ router.back())}
+ style={[styles.iconButton, glass && styles.iconButtonGlass]}
+ >
+
+
+ )}
+
+
+ {overline && variant === 'large' && {overline}}
+ {title && (
+
+ {title}
+
+ )}
+
+
+ {right ?? (showBack && variant === 'compact' ? : null)}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ row: { flexDirection: 'row', alignItems: 'center', gap: 12, paddingTop: 6, paddingBottom: 14 },
+ compactRow: { paddingBottom: 10 },
+ absolute: { position: 'absolute', top: 0, left: 0, right: 0, zIndex: 10, paddingHorizontal: 20 },
+
+ titleWrap: { flex: 1, minWidth: 0, gap: 2 },
+ titleWrapCentered: { alignItems: 'center' },
+ overline: { ...typography.overlineSm, color: colors.textSecondary },
+ titleLarge: { ...typography.screenTitleLg, color: colors.textPrimary },
+ titleCompact: { ...typography.cardTitle, color: colors.textPrimary },
+
+ iconButton: {
+ width: 44,
+ height: 44,
+ borderRadius: 14,
+ backgroundColor: colors.surface,
+ borderWidth: 1,
+ borderColor: colors.border,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ iconButtonGlass: { backgroundColor: colors.glassFill, borderColor: 'transparent' },
+ spacer: { width: 44 },
+});
\ No newline at end of file
diff --git a/src/components/ui/Screen.tsx b/src/components/ui/Screen.tsx
new file mode 100644
index 0000000..41d39b0
--- /dev/null
+++ b/src/components/ui/Screen.tsx
@@ -0,0 +1,75 @@
+/* ------------------------------------------------------------------ *
+ * Screen — enveloppe d'écran. Fond, zone sûre, padding de tab bar.
+ * ------------------------------------------------------------------ */
+import { ReactNode } from 'react';
+import { ScrollView, StyleSheet, View, ViewStyle } from 'react-native';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+
+import { colors } from '@/theme/colors';
+
+/** Hauteur de la tab bar custom, hors safe-area. Source unique. */
+import { TAB_BAR_BASE_HEIGHT } from '@/components/navigation/BahlaTabBar';
+export const TAB_BAR_HEIGHT = TAB_BAR_BASE_HEIGHT;
+
+type Props = {
+ children: ReactNode;
+ /** `scroll` enveloppe dans un ScrollView, `static` en View simple. */
+ layout?: 'scroll' | 'static';
+ /** Applique le padding haut de la zone sûre. false pour un écran à image plein bord. */
+ edgeToEdge?: boolean;
+ /** Réserve la hauteur de la tab bar en bas. false sur les écrans modaux / (org)/create. */
+ tabBar?: boolean;
+ /** Halo violet décoratif en haut à gauche (B1, C1). */
+ halo?: boolean;
+ /** Padding horizontal des enfants. 20 par défaut, 0 pour du plein bord. */
+ gutter?: number;
+ contentContainerStyle?: ViewStyle;
+};
+
+export function Screen({
+ children,
+ layout = 'scroll',
+ edgeToEdge = false,
+ tabBar = true,
+ halo = false,
+ gutter = 20,
+ contentContainerStyle,
+}: Props) {
+ const insets = useSafeAreaInsets();
+
+ const padding: ViewStyle = {
+ paddingTop: edgeToEdge ? 0 : insets.top,
+ paddingHorizontal: gutter,
+ paddingBottom: tabBar ? TAB_BAR_HEIGHT + insets.bottom + 24 : insets.bottom + 24,
+ };
+
+ return (
+
+ {halo && }
+ {layout === 'scroll' ? (
+
+ {children}
+
+ ) : (
+ {children}
+ )}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ root: { flex: 1, backgroundColor: colors.deepBackground },
+ flex: { flex: 1 },
+ halo: {
+ position: 'absolute',
+ width: 380,
+ height: 380,
+ borderRadius: 190,
+ top: -140,
+ left: -60,
+ backgroundColor: colors.secondarySoft,
+ },
+});
\ No newline at end of file
diff --git a/src/global.css b/src/global.css
deleted file mode 100644
index bd6213e..0000000
--- a/src/global.css
+++ /dev/null
@@ -1,3 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
\ No newline at end of file
diff --git a/src/stores/authStore.ts b/src/stores/authStore.ts
index 4ba9d05..bbb0de9 100644
--- a/src/stores/authStore.ts
+++ b/src/stores/authStore.ts
@@ -13,7 +13,7 @@ const DEV_MOCK_SESSION_ENABLED = true;
const DEV_MOCK_SESSION: Session = {
userId: 'dev-user',
token: 'dev-token',
- role: 'org',
+ role: 'user',
};
type AuthState = {
diff --git a/tailwind.config.js b/tailwind.config.js
deleted file mode 100644
index d27d790..0000000
--- a/tailwind.config.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/** @type {import('tailwindcss').Config} */
-module.exports = {
- content: ["src/**/*.{html,js,ts,jsx,tsx}"],
- presets: [require("nativewind/preset")],
- theme: {
- extend: {},
- },
- plugins: [],
-}
-