Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/every-vans-clean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@perimetre/tokens': minor
'@perimetre/ui': minor
---

Add microbird brand support to `FieldGooglePlacesAutocomplete`
4 changes: 4 additions & 0 deletions packages/tokens/dist/brands/microbird-commercial.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
[data-pui-brand='microbird-commercial'] {
--pui-color-interactive-on-primary: var(--pui-primitive-color-primary-1);
--pui-color-button-secondary-outline: #22222233;
--pui-color-input-bg: #FFFFFF;
--pui-color-input-border: #22222233;
--pui-color-input-placeholder: var(--pui-primitive-color-primary-9);
--pui-color-alertbar-first-fg: var(--pui-primitive-color-primary-1);
--pui-radius-input: 2rem;
--pui-typo-heading-1-size: 6.25rem;
--pui-typo-heading-1-weight: var(--pui-primitive-font-weight-semibold);
--pui-typo-heading-1-tracking: -0.01em;
Expand Down
4 changes: 4 additions & 0 deletions packages/tokens/dist/brands/microbird-school.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
[data-pui-brand='microbird-school'] {
--pui-color-fg-link-active: var(--pui-primitive-color-overlay-12);
--pui-color-button-secondary-outline: #22222233;
--pui-color-input-bg: #FFFFFF;
--pui-color-input-border: #22222233;
--pui-color-input-placeholder: var(--pui-primitive-color-primary-9);
--pui-radius-input: 2rem;
--pui-typo-heading-1-size: 6.25rem;
--pui-typo-heading-1-weight: var(--pui-primitive-font-weight-semibold);
--pui-typo-heading-1-tracking: -0.01em;
Expand Down
21 changes: 21 additions & 0 deletions packages/tokens/src/sets/brands/microbird-commercial.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,27 @@
"$value": "#22222233",
"$description": "Button outline border — overlay-12 at 20% opacity."
}
},
"input": {
"bg": {
"$value": "#FFFFFF",
"$description": "Input background is pure white on microbird (vs Acorn's default surface)."
},
"border": {
"$value": "#22222233",
"$description": "Input border — overlay-12 at 20% opacity (matches button secondary-outline)."
},
"placeholder": {
"$value": "{pui.primitive.color.primary.9}",
"$description": "Placeholder uses the brand primary-9 navy so the gmp shadow-DOM input picks it up through CSS-custom-property inheritance."
}
}
},
"radius": {
"$type": "borderRadius",
"input": {
"$value": "2rem",
"$description": "Microbird inputs are pill-shaped (rounded-4xl). Cascades to the gmp shadow-DOM input via --pui-radius-input."
}
}
}
Expand Down
21 changes: 21 additions & 0 deletions packages/tokens/src/sets/brands/microbird-school.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,27 @@
"$value": "#22222233",
"$description": "Button outline border — overlay-12 at 20% opacity."
}
},
"input": {
"bg": {
"$value": "#FFFFFF",
"$description": "Input background is pure white on microbird (vs Acorn's default surface)."
},
"border": {
"$value": "#22222233",
"$description": "Input border — overlay-12 at 20% opacity (matches button secondary-outline)."
},
"placeholder": {
"$value": "{pui.primitive.color.primary.9}",
"$description": "Placeholder uses the brand primary-9 yellow so the gmp shadow-DOM input picks it up through CSS-custom-property inheritance."
}
}
},
"radius": {
"$type": "borderRadius",
"input": {
"$value": "2rem",
"$description": "Microbird inputs are pill-shaped (rounded-4xl). Cascades to the gmp shadow-DOM input via --pui-radius-input."
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { cva } from '@/lib/cva';

/**
* Acorn brand FieldGooglePlacesAutocomplete container variants (default/base theme).
*
* Layered on top of `inputVariants` from FieldBaseInput — captures the overlay
* styling that is specific to this component (the real input lives inside the
* gmp-place-autocomplete shadow DOM, so we use `focus-within:*` rather than
* `focus:*` for the outer container).
*
* Semantic tokens used (brand-overridable via CSS):
* - bg-pui-bg-subtle / text-pui-fg-subtle / border-pui-bg-subtle (disabled)
* - border-pui-input-border-focus (focus-within border)
* - shadow-pui-input-focus (focus-within ring)
* - color-pui-feedback-error (error focus-within ring)
*/
export const fieldGooglePlacesAutocompleteAcornVariants = cva({
base: ['pui:flex pui:items-center'],
variants: {
disabled: {
false: null,
true: 'pui:cursor-not-allowed pui:bg-pui-bg-subtle pui:text-pui-fg-subtle pui:border-pui-bg-subtle'
},
error: {
false: null,
true: null
}
},
compoundVariants: [
{
disabled: false,
error: false,
class:
'pui:focus-within:outline-none pui:focus-within:border-pui-input-border-focus pui:focus-within:shadow-pui-input-focus'
},
{
disabled: false,
error: true,
class:
'pui:focus-within:outline-none pui:focus-within:border-pui-input-border-focus pui:focus-within:shadow-[0_0_0_2px_var(--color-pui-feedback-error)]'
}
],
defaultVariants: {
disabled: false,
error: false
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { cva } from '@/lib/cva';

/**
* MicroBird Commercial brand FieldGooglePlacesAutocomplete container variants.
*
* Composed on top of Acorn via `compose()` in `brands/index.ts`. All
* brand-level differences (input bg, border, placeholder colour, radius)
* are handled via semantic CSS tokens overridden in
* `packages/tokens/src/sets/brands/microbird-commercial.json`. This file is
* kept as scaffolding so future class-level differences (typography,
* decoration, brand-specific structural overrides) can be added here
* without touching the registry.
*/
export const fieldGooglePlacesAutocompleteMicroBirdCommercialVariants = cva({
base: []
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { cva } from '@/lib/cva';

/**
* MicroBird School brand FieldGooglePlacesAutocomplete container variants.
*
* Composed on top of Acorn via `compose()` in `brands/index.ts`. All
* brand-level differences (input bg, border, placeholder colour, radius)
* are handled via semantic CSS tokens overridden in
* `packages/tokens/src/sets/brands/microbird-school.json`. This file is
* kept as scaffolding so future class-level differences (typography,
* decoration, brand-specific structural overrides) can be added here
* without touching the registry.
*/
export const fieldGooglePlacesAutocompleteMicroBirdSchoolVariants = cva({
base: []
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { type BrandVariants } from '@/lib/brand-registry';
import { compose } from '@/lib/cva';
import { type VariantProps } from 'cva';
import { fieldGooglePlacesAutocompleteAcornVariants } from './FieldGooglePlacesAutocomplete.acorn.brand';
import { fieldGooglePlacesAutocompleteMicroBirdCommercialVariants } from './FieldGooglePlacesAutocomplete.microbird-commercial.brand';
import { fieldGooglePlacesAutocompleteMicroBirdSchoolVariants } from './FieldGooglePlacesAutocomplete.microbird-school.brand';

export const fieldGooglePlacesAutocompleteBrandVariants = {
acorn: fieldGooglePlacesAutocompleteAcornVariants,
'microbird-commercial': compose(
fieldGooglePlacesAutocompleteAcornVariants,
fieldGooglePlacesAutocompleteMicroBirdCommercialVariants
),
'microbird-school': compose(
fieldGooglePlacesAutocompleteAcornVariants,
fieldGooglePlacesAutocompleteMicroBirdSchoolVariants
)
} as const satisfies BrandVariants<
typeof fieldGooglePlacesAutocompleteAcornVariants
>;

export type FieldGooglePlacesAutocompleteVariantProps = VariantProps<
typeof fieldGooglePlacesAutocompleteAcornVariants
>;
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { useGoogleContext } from '@/components/GoogleProvider';
import { getBrandVariant } from '@/lib/brand-registry';
import { cx } from '@/lib/cva';
import { type ForceRequiredProps } from '@perimetre/helpers/types';
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
Expand All @@ -9,6 +10,7 @@ import { inputVariants } from '../FieldBaseInput';
import FieldContainer from '../FieldContainer';
import FieldLower, { type FieldLowerProps } from '../FieldLower';
import FieldUpper, { type FieldUpperProps } from '../FieldUpper';
import { fieldGooglePlacesAutocompleteBrandVariants } from './brands';

export type FieldGooglePlacesAutocompleteProps = {
containerClassName?: string;
Expand Down Expand Up @@ -792,22 +794,17 @@ const FieldGooglePlacesAutocomplete: React.FC<
aria-describedby={ariaDescribedBy}
aria-invalid={!!error || undefined}
id={`${name}-input`}
className={inputVariants({
className: cx(
'pui:flex pui:items-center',
disabled &&
'pui:cursor-not-allowed pui:bg-pui-bg-subtle pui:text-pui-fg-subtle pui:border-pui-bg-subtle',
!disabled &&
'pui:focus-within:outline-none pui:focus-within:border-pui-input-border-focus',
!disabled &&
(error
? 'pui:focus-within:shadow-[0_0_0_2px_var(--color-pui-feedback-error)]'
: 'pui:focus-within:shadow-pui-input-focus')
),
error: !!error,
leading: !!leading,
trailing: !!trailing
})}
className={cx(
inputVariants({
error: !!error,
leading: !!leading,
trailing: !!trailing
}),
getBrandVariant(fieldGooglePlacesAutocompleteBrandVariants)({
disabled: !!disabled,
error: !!error
})
)}
>
{/* Placeholder input — defines the container height and shows
during SSR / before Google API loads. When a defaultValue is
Expand All @@ -817,10 +814,13 @@ const FieldGooglePlacesAutocomplete: React.FC<
<input
aria-hidden
disabled
className={isLoaded || !defaultValue ? 'pui:invisible' : undefined}
defaultValue={defaultValue}
placeholder={isLoaded ? undefined : placeholder}
tabIndex={-1}
className={cx(
'pui:placeholder:text-pui-input-placeholder',
(isLoaded || !defaultValue) && 'pui:invisible'
)}
style={{
background: 'transparent',
border: 'none',
Expand Down
Loading
Loading