Skip to content
Open
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
20 changes: 10 additions & 10 deletions src/foundations/about/page.mdx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
export const metadata = {
title: "About",
description:
"Foundations is an opinionated collection of components, patterns, and guidelines for building modern digital products",
"Foundations is an opinionated collection of components, patterns, and guidelines for building modern digital products.",
};

## What is Foundations?

Foundations is an opinionated collection of components, patterns, and guidelines for building modern digital products. While it includes a robust set of UI components, it goes far beyond basic interface elements to provide comprehensive resources for building complete digital experiences.
Foundations is an opinionated collection of components, patterns, and guidelines for building modern digital products. While it includes a robust set of UI components, it goes far beyond basic interface elements to provide comprehensive resources for creating complete digital experiences.

From web applications to marketing sites, Foundations covers everything from foundational UI components to advanced interaction patterns, state management strategies, content modeling, and performance optimizations. It's designed to help developers create high-quality digital products by providing well-documented, tested, and production-ready solutions.
From web applications to marketing sites, Foundations covers everything from foundational UI components to advanced interaction patterns, state management strategies, content modelling, and performance optimisations. It's designed to help developers create high-quality digital products by providing well-documented, tested, and production-ready solutions.

## How to use Foundations

There are two main ways to use Foundations:

1. **Copy and Customize**: Take the components, patterns, or entire feature implementations you need and integrate them directly into your project. Each solution is designed to be self-contained and easily customizable. This approach gives you full control over the code and allows you to modify it to match your specific requirements.
1. **Copy and Customise**: Take the components, patterns, or entire feature implementations you need and integrate them directly into your project. Each solution is designed to be self-contained and easily customizable. This approach gives you full control over the code and allows you to modify it to match your specific requirements.

2. **Learning Resource**: Use Foundations as a reference and learning tool. Study our implementation patterns, from accessibility considerations in UI components to complex state management in applications, or content modeling for data-heavy products. This knowledge can help you build your own solutions from scratch with confidence.
2. **Learning Resource**: Use Foundations as a reference and learning tool. Study our implementation patterns, from accessibility considerations in UI components to complex state management in applications, or content modelling for data-heavy products. This knowledge can help you build your own solutions from scratch with confidence.

## Project context

Expand All @@ -26,7 +26,7 @@ Foundations was created by [Significa](https://significa.co) as an internal reso
- Bootstrap new projects with proven, production-ready solutions
- Speed up development while maintaining high standards for user experience, accessibility, and performance
- Share knowledge and promote good practices within our team
- Standardize our approach to common challenges in web development
- Standardise our approach to common challenges in web development

While this is primarily an internal tool, we've made it open source to contribute to the developer community and share our learnings.

Expand All @@ -36,7 +36,7 @@ Foundations draws inspiration from several excellent projects in the developer c

- [shadcn/ui](https://ui.shadcn.com/): For its innovative approach to component distribution and documentation
- [Lucia Auth](https://lucia-auth.com/): For its excellent documentation structure and learning resources
- Other similar projects that prioritize education and flexibility over traditional dependency-based solutions
- Other similar projects that prioritise education and flexibility over traditional dependency-based solutions

However, we take a broader approach. While these projects focus on specific aspects of web development, Foundations aims to be a comprehensive resource covering the full spectrum of modern web development, from UI components to complete application architectures and beyond.

Expand All @@ -45,18 +45,18 @@ What sets Foundations apart is our focus on:
- Complete solutions over isolated components
- Production-ready patterns over basic implementations
- Real-world scenarios over simplified examples
- Documentation over dependencies
- Documentation on dependencies
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this changed the message, it's not what we're going for

- Learning resources over black-box solutions
- Flexibility over one-size-fits-all approaches

## Philosophy

Unlike traditional libraries that you install as dependencies, Foundations takes a different approach:

- Solutions are meant to be copied and customized
- Solutions are meant to be copied and customised
- Documentation explains not just what things do, but why and how they work
- Code is written to be read and understood, not just used
- Best practices for accessibility, performance, and SEO are built-in, not afterthoughts
- Best practices for accessibility, performance, and SEO are built in, not afterthoughts
- Patterns are based on real-world production use, not theoretical examples

This approach means you're not tied to our update cycle, version constraints, or design decisions. You have full control over the code you use, while still benefiting from our years of experience building digital products.
Expand Down
2 changes: 1 addition & 1 deletion src/foundations/components/instance-counter/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ Returns a `number` that represents the current index of the component within the

## Limitations

The indices are assigned based on the order of React's `useEffect` hook execution. While this generally matches the DOM order, if, for some reason, it does not, it may lead to unexpected behavior.
The indices are assigned based on the order of React's `useEffect` hook execution. While this generally matches the DOM order, if, for some reason, it does not, it may lead to unexpected behaviour.
6 changes: 3 additions & 3 deletions src/foundations/components/marquee/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ export const metadata = {

## Features

- **Native-Like Implementation**: Closely mirrors the behavior of the native (now deprecated) marquee element, including maintaining a single-element structure
- **Native-Like Implementation**: Closely mirrors the behaviour of the native (now deprecated) marquee element, including maintaining a single-element structure
- **Dynamic Content Cloning**: Automatically creates the optimal number of content clones based on element size and content length
- **Automatic Text Wrapping**: Text content is automatically wrapped in `<span>` elements to ensure proper rendering with CSS transforms
- **Customizable Gap**: Supports flexible spacing between items using CSS gap property, allowing for consistent and adjustable spacing between content elements
- **Customizable Gap**: Supports flexible spacing between items using the CSS gap property, allowing for consistent and adjustable spacing between content elements
- **Intersection Observer**: Pauses animation when not in viewport
- **Flexible Duration Control**: Duration can be specified as:
- A fixed number
Expand Down Expand Up @@ -75,4 +75,4 @@ export const metadata = {

## Best Practices

**Avoid Media Without Dimensions**: when using images or videos in a marquee, always specify explicit `width` and `height` attributes. Without proper dimensions, the content may cause layout shifts as it loads, disrupting the smooth scrolling behavior. This is especially important since the marquee needs to calculate the total content length to determine scrolling speed and clone count.
**Avoid Media Without Dimensions**: When using images or videos in a marquee, always specify explicit `width` and `height` attributes. Without proper dimensions, the content may cause layout shifts as it loads, disrupting the smooth scrolling behaviour. This is especially important since the marquee needs to calculate the total content length to determine scrolling speed and clone count.
6 changes: 3 additions & 3 deletions src/foundations/components/sequence/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ export const metadata = {
## Features

- **Automatic Progression**: Items advance automatically based on configurable durations
- **Progress Indication**: Exposes a `--progress` css variable to show progression through each item, and a `--index` css variable to show the current index
- **Progress Indication**: Exposes a `--progress` CSS variable to show progression through each item, and a `--index` css variable to show the current index
- **Keyboard Navigation**: Full keyboard support for manual navigation
- **ARIA Support**: Full accessibility implementation with proper ARIA attributes
- **Unstyled**: No default styles, just the sequence behavior
- **Unstyled**: No default styles, just the sequence behaviour
- **Intersection Observer**: Pauses progression when not in viewport

## Anatomy
Expand All @@ -54,7 +54,7 @@ export const metadata = {

### Sequence

The root container component that manages the state and behavior of the sequence.
The root container component that manages the state and behaviour of the sequence.

<PropsTable
definition={{
Expand Down
2 changes: 1 addition & 1 deletion src/foundations/components/stack/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const metadata = {

## Features

- **Unstyled**: No default styles, just the sticky behavior
- **Unstyled**: No default styles, just the sticky behaviour
- **Automatic**: Handles all offset calculations and supports dynamic content heights
- **Native**: Uses `position: sticky` under the hood without any on-scroll logic, so it's performant and works in all browsers
- **No exit overlap**: Trailing item never overlaps with the header when exiting the viewport (see [Stack vs. Manual `position: sticky`](/preview/stack-vs-sticky?layout=fullscreen))
Expand Down
26 changes: 13 additions & 13 deletions src/foundations/guides/accessible-forms/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ export const metadata = {
## Overview

For form-heavy products, creating accessible forms can be a bit of a challenge.
Even if it's easy enough to connect labels to fields, suddenly you're asked to add descriptions and error messages and the code gets too verbose with ids and attributes everywhere.
Even if it's easy enough to connect labels to fields, suddenly you're asked to add descriptions and error messages, and the code gets too verbose with IDs and attributes everywhere.

This guide offers an alternative approach where most of the usual connections between form elements, labels, descriptions and error messages are handled automatically.

### Why a guide?

- Simple products can get by with a simpler approach
- It's not a one-size-fits-all solution
- It's best if you understand what's going on instead of having this functionality baked in the components by default
- It's best if you understand what's going on instead of having this functionality baked into the components by default

## Source Code

The idea is to create a Field component that will act basically as a Provider and exposes attributes and methods to register elements.
The idea is to create a Field component that will act basically as a Provider and expose attributes and methods to register elements.

### Field

Expand All @@ -32,7 +32,7 @@ It will also allow you to easily improve your form components by adding the appr

### FieldError

Field errors hooks up to the Field's context and will automatically register itself as an error message.
Field errors hook up to the Field's context and will automatically register themselves as an error message.

<SourceCode
file="src/foundations/guides/accessible-forms/field-error.tsx"
Expand All @@ -41,7 +41,7 @@ Field errors hooks up to the Field's context and will automatically register its

### FieldDescription

Field descriptions hooks up to the Field's context and will automatically register itself as a description.
Field descriptions hook up to the Field's context and will automatically register themselves as a description.

<SourceCode
file="src/foundations/guides/accessible-forms/field-description.tsx"
Expand All @@ -52,9 +52,9 @@ Field descriptions hooks up to the Field's context and will automatically regist

### Form elements

Add the following code yo your `input.tsx`, `textarea.tsx`, `checkbox.tsx`, `switch.tsx`, and similar components.
Add the following code to your `input.tsx`, `textarea.tsx`, `checkbox.tsx`, `switch.tsx`, and similar components.

> Warning: If you have custom components that use buttons instead of the native elements, you should ommit the `aria-errormessage` and `aria-invalid` attributes. See [Custom Selects](#custom-selects) below.
> Warning: If you have custom components that use buttons instead of the native elements, you should omit the `aria-errormessage` and `aria-invalid` attributes. See [Custom Selects](#custom-selects) below.

```tsx {2,4,5,9-13} showLineNumbers title="input.tsx"
const Input = ({ invalid: propsInvalid, id, ...props }: InputProps) => {
Expand All @@ -78,7 +78,7 @@ const Input = ({ invalid: propsInvalid, id, ...props }: InputProps) => {

### Custom Selects

If you are using a custom `Select` component that uses a button instead of a native select element, you should ommit the `aria-errormessage` and `aria-invalid` attributes as they're reserved for form elements that can have validation errors (such as `input`, `textarea` and `select`):
If you are using a custom `Select` component that uses a button instead of a native select element, you should omit the `aria-errormessage` and `aria-invalid` attributes as they're reserved for form elements that can have validation errors (such as `input`, `textarea` and `select`):

```tsx {2,4,8-10} showLineNumbers title="select.tsx"
const SelectTrigger = ({ children, id, ...props }: SelectTriggerProps) => {
Expand All @@ -101,7 +101,7 @@ const SelectTrigger = ({ children, id, ...props }: SelectTriggerProps) => {

### Radio and Radio Groups

Radio buttons are a bit special as they need to be grouped together, so the aria attributes should be set on the `RadioGroup` component instead:
Radio buttons are a bit special as they need to be grouped, so the aria attributes should be set on the `RadioGroup` component instead:

```tsx showLineNumbers title="radio-group.tsx"
interface RadioGroupProps extends React.ComponentPropsWithRef<"div"> {
Expand Down Expand Up @@ -150,7 +150,7 @@ Given that we'll have a nested structure, we'll also need some attributes on the
</Field>
```

We'll just add the `id` and `aria-describedby` attribute:
We'll just add the `id` and `aria-describedby` attributes:

```tsx {6,11,12} showLineNumbers
const Radio = ({
Expand Down Expand Up @@ -220,9 +220,9 @@ export { Label };

## Fieldset and Legend

A `fieldset` is an HTML element used to group related elements within a form, providing a semantic way to organize form controls. It is often used in conjunction with the `<legend>` element, which provides a caption for the group.
A `fieldset` is an HTML element used to group related elements within a form, providing a semantic way to organise form controls. It is often used in conjunction with the `<legend>` element, which provides a caption for the group.

This grouping not only helps with visual organization but also improves accessibility by allowing screen readers to understand the relationship between grouped elements.
This grouping not only helps with visual organisation but also improves accessibility by allowing screen readers to understand the relationship between grouped elements.

Here we create a `Fieldset` component that will automatically register the `Legend` elements and expose them to the `Field` context.

Expand Down Expand Up @@ -251,7 +251,7 @@ You can add a `FieldDescription` and `FieldError` to the `Field` component:
<div>
<Label>Name</Label>
<FieldDescription>
This is a description very very long description
This is a very, very long description
</FieldDescription>
</div>
<Input {...register("name", { required: true })} />
Expand Down
Loading